为何JSF中outputText可用的转换器在selectOneMenu中失效?
嘿,我明白你遇到的问题了——<h:outputText>里用自定义转换器好好的,一放到<p:selectOneMenu>就失效,这俩组件对转换器的需求确实不一样,我来给你捋清楚:
首先得搞清楚核心差异:<h:outputText>是单向渲染,只需要把后端对象转成前端显示的字符串就行,所以你的转换器只用到了getAsString方法;但<p:selectOneMenu>是双向绑定组件,既要把后端对象转成前端显示的选项标签,还要在表单提交时把用户选中的字符串转回到后端对象,这就要求你的转换器必须实现Converter接口的两个方法:getAsString(显示用)和getAsObject(提交用)。如果你的<gn:converter>没实现后者,那肯定会失效。
接下来给你两种常见场景的正确写法:
场景1:选项值是后端对象,标签需要转成指定属性
假设你的下拉选项是一堆pays对象,要把每个对象的libelleImpression作为显示标签,同时选中的对象直接绑定到后台属性,那应该把转换器放到<f:selectItems>的itemLabel绑定上:
<p:selectOneMenu id="pays" value="#{InformationsPersonnellesModele.adressePrincipale.pays}"> <!-- 这里替换成你的pays列表数据源 --> <f:selectItems value="#{paysDataSource.allPays}" var="paysItem" itemValue="#{paysItem}" itemLabel="#{paysItem}"> <!-- 把转换器应用到itemLabel的转换上 --> <gn:converter origine="#{config.origManSirhen}" nomenclature="#{config.codePays}" propriete="libelleImpression" /> </f:selectItems> </p:selectOneMenu>
场景2:选项值是字符串(比如pays的编码),绑定的是后端对象
如果你的下拉选项用的是pays的编码字符串,而后台绑定的是pays对象,那应该把转换器直接放到<p:selectOneMenu>内部,让它处理双向转换:
<p:selectOneMenu id="pays" value="#{InformationsPersonnellesModele.adressePrincipale.pays}"> <!-- 转换器直接作用于整个组件的双向转换 --> <gn:converter origine="#{config.origManSirhen}" nomenclature="#{config.codePays}" propriete="libelleImpression" /> <!-- 选项值是编码字符串,标签可以用编码或者转成对应名称 --> <f:selectItems value="#{paysDataSource.allPaysCodes}" var="paysCode" itemValue="#{paysCode}" itemLabel="#{paysCode}" /> </p:selectOneMenu>
额外排查点
- 先看服务器日志!如果转换器失效,大概率会抛出
ConverterException,日志里会告诉你是getAsObject还是getAsString出了问题,这能快速定位bug。 - 确认你的
<gn:converter>确实支持双向转换——有些自定义转换器可能只实现了单向的字符串转换,没处理反向的对象转换,这时候就得给它补上getAsObject的逻辑。
内容的提问来源于stack exchange,提问作者Alex Blasco
相关产品推荐
相关产品推荐

