今作っているWEBアプリで、画面に一覧を表示して、一覧表示内の項目値によって背景色を変えたいという要件がありました。
で、JSF2のカスタムコンバータを使って、コード値を文言にデコードしつつ、裏でCSSクラスを変えることで背景色が動的に変わる形にしてみました。コンバータは一つで、どのコード体系でデコードするかは、attributeでコンバータに情報を渡す構成になってます、とりあえずは。。
CSS抜粋
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
.listTable th { font-weight: normal; color: #ffffff; background-color: #339933; text-align: center; padding: 1px; border-right-style: solid; border-bottom-style: solid; border-right-color: #CCCCCC; border-bottom-color: #CCCCCC; font-size: 10pt; white-space: nowrap; } .listTable td { padding: 1px; background-color: #ffffff; border-right-style: solid; border-bottom-style: solid; border-right-color: #CCCCCC; border-bottom-color: #CCCCCC; font-size: 11pt; } /* 警告表示 */ .cError { background-color: #ff0000; color: #ffffff; display:block; } /* 一部異常表示 */ .cCaution { background-color: #ffff00; display:block; } /* 対象外表示 */ .cNoTaget { background-color: #a4a4a4; display:block; } /* 通常表示 */ .cDefault { background-color: #ffffff; display:block; } |
xhtmlのdataTable部分抜粋
※wordsはwords.propertiesのファイル側に定義している項目タイトルの文言です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<h:dataTable id="Info" var="list" value="#{listView.itemlist}" styleClass="listTable"> <h:column> <f:facet name="header" >#{words.Label_coName}</f:facet> <h:outputText value="#{list.coName}"/> </h:column> <h:column> <f:facet name="header" >#{words.Label_coCode}</f:facet> <h:outputText value="#{list.coCode}"/> </h:column> <h:column> <f:facet name="header" >#{words.Label_status1}</f:facet> <h:outputText value="#{list.status1}"> <f:converter converterId="statusConverter"/> <f:attribute name="ConvertType" value="1"/> </h:outputText> </h:column> <h:column> <f:facet name="header" >#{words.Label_status2}</f:facet> <h:outputText value="#{list.status2}"> <f:converter converterId="statusConverter"/> <f:attribute name="ConvertType" value="2"/> </h:outputText> </h:column> 以下省略 </h:dataTable> |
カスタムコンバータ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
@FacesConverter(value="statusConverter") public class StatusConverter implements Converter { private static final String DEFVALUE = "X"; private static final String DEFAULT = "cDefault"; private static final String NOTARGET = "cNoTaget"; private static final String CAUTION = "cCaution"; private static final String ERROR = "cError"; // ConvertType 1 OKNG表示 private static final Map<String, String> OkNgState; static { HashMap<String, String> map = new HashMap<String, String>(); map.put(DEFVALUE, "-"); map.put("1", "OK"); map.put("2", "NG"); OkNgState = Collections.unmodifiableMap(map); } // ConvertType 2 現在状況表示 private static final Map<String, String> NowState; static { HashMap<String, String> map = new HashMap<String, String>(); map.put(DEFVALUE, "-"); map.put("0", "処理前"); map.put("1", "仕掛中"); map.put("2", "処理済"); NowState = Collections.unmodifiableMap(map); } // ConvertType 3 結果表示 private static final Map<String, String> ResStatus; static { HashMap<String, String> map = new HashMap<String, String>(); map.put(DEFVALUE, "-"); map.put("0", "正常"); map.put("1", "異常"); map.put("2", "警告"); ResStatus = Collections.unmodifiableMap(map); } //警告表示対象 private static final Map<String, String> Caution; static { HashMap<String, String> map = new HashMap<String, String>(); map.put("異常", ERROR); map.put("警告", CAUTION); map.put("-", NOTARGET); Caution = Collections.unmodifiableMap(map); } @Override public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) { String DispValue=""; String InnerValue = (String) arg2; String StyleClass = DEFAULT; Map<String,String> ConvertMap = null; Map<String,Object> attrMap = arg1.getAttributes(); //f:attribute より変換タイプを取得 String type = (String)attrMap.get("ConvertType"); if (! StringUtils.isNumeric(type) ){ return ""; } switch (Integer.valueOf(type)){ case 1: ConvertMap = OkNgState; break; case 2: ConvertMap = NowState; break; case 3: ConvertMap = ResStatus; break; default: DispValue = InnerValue; ConvertMap = null; break; } //デコード if(ConvertMap != null){ DispValue = ConvertMap.get(InnerValue); //初期値 if (DispValue == null ){ DispValue = ConvertMap.get(DEFVALUE); } } //スタイルクラス指定 if(Caution.get(DispValue) != null){ StyleClass = Caution.get(DispValue); } } //色変 if (arg1.getClass() == HtmlOutputText.class){ HtmlOutputText ui = (HtmlOutputText) arg1; ui.setStyleClass(StyleClass); } return DispValue; } //こっちは関係無し @Override public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { return null; } } |
ManagedBean抜粋
※一覧表示対象のitemInfoの実装は割愛します。プロパティとゲッタ・セッタがあるだけです。。
1 2 3 4 5 6 7 8 9 10 |
@ManagedBean(name="listView") @ViewScoped public class ListView { private List<itemInfo> itemlist; public List<itemInfo> getitemlist() { //ここでitemlistのデータをセットしてますが省略します return itemlist; } 以下、省略 |
こんな感じで表示できそうなので、別途整理して実装します。
上記例では色が変わるのは行でなくセル単位になります。なお、dataTableの場合、その中のoutputTextはdivに置き換えらえるようなので、コンバータではtdのスタイルを変えているのではなくdivが対象になってます。それをCSSでカバーしているのですが、CSSは得意でないので。。