【问题标题】:Using converters in data table filters in PrimeFaces 5.0 final在 PrimeFaces 5.0 final 的数据表过滤器中使用转换器
【发布时间】:2018-07-26 19:12:33
【问题描述】:

给定以下 XHTML 代码(关于 PrimeFaces 5.0 final)。可以看到对数据表过滤器的新更改here

<p:dataTable id="dataTable" var="row" value="#{testManagedBean}"
             lazy="true"
             rowKey="#{row.transporterId}"
             widgetVar="dataTableUIWidget">

    <p:column id="id" headerText="Id" sortBy="#{row.transporterId}">
        <h:outputText value="#{row.transporterId}"/>
    </p:column>

    <p:column id="transporter" headerText="Transporter" filterBy="#{row.transporterName}">
        <f:facet name="filter">
            <p:inputText onkeyup="PF('dataTableUIWidget').filter();"/>
        </f:facet>
        <h:outputText value="#{row.transporterName}"/>
    </p:column>
</p:dataTable>

以下是从字符串中修剪前导和尾随空格的面孔转换器。

@FacesConverter(forClass=String.class)
public final class StringTrimmer implements Converter
{
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        return value != null ? value.trim() : null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (String) value;
    }
}

此转换器能否全局应用于数据表中指定的所有字符串类型的过滤器(包括其他 UI 组件已应用)?

<f:facet name="filter">
    <p:inputText onkeyup="PF('dataTableUIWidget').filter();"/>
</f:facet>

或者我必须修改转换器类以具有类似的注释,

@ManagedBean
@RequestScoped
public final class StringTrimmer implements Converter
{
    //...
}

然后像这样手动将此转换器应用于所有有问题的过滤器,

<f:facet name="filter">
    <p:inputText onkeyup="PF('dataTableUIWidget').filter();" converter="#{stringTrimmer}"/>
</f:facet>

这个转换器能否以某种方式全局应用,这样我们就不需要为所有字符串类型过滤器显式指定converter="#{stringTrimmer}"

这个问题应该更多地与 JSF 而不是 PrimeFaces 相关。

【问题讨论】:

    标签: jsf primefaces jsf-2.2


    【解决方案1】:

    这是因为UIInput#getValue() 默认为Object,而不是String。只要您没有将基于UIInput 的组件的value 属性显式绑定到更特定类型的支持bean 属性,例如String,也不会查找特定转换器。

    如果你改变它应该可以工作

    <p:inputText onkeyup="PF('dataTableUIWidget').filter();"/>
    

    例如

    <p:inputText value="#{bean.filter}" onkeyup="PF('dataTableUIWidget').filter();"/>
    

    带有private String filter 属性(和getter+setter)。但是,如果您不在模型中的其他任何地方使用此属性,这确实很混乱。

    替代方案确实是通过converter 属性显式声明转换器。根据@FacesConverter 合同,不可能像这样在同一个转换器类上同时声明转换器 ID 和转换器类。

    @FacesConverter(value="stringTrimmer", forClass=String.class)
    public final class StringTrimmer implements Converter {
        // ...
    }
    

    只会注册转换器 ID,并且会在服务器日志中打印警告。

    警告:@FacesConverter 同时使用 value 和 forClass,只会应用 value。

    但是,@ManagedBean@FacesConverter 可以在同一类中同时拥有。您应该只了解它们不相互合作并且将创建完全独立的实例。但是,如果转换器被设计为无状态的(即所有状态都保存在方法块中并且类没有任何实例变量/依赖项),这应该不会造成伤害。

    @ManagedBean
    @ApplicationScoped
    @FacesConverter(forClass=String.class)
    public final class StringTrimmer implements Converter {
        // ...
    }
    

    通过这种方式,您可以继续享受forClass 的好处,并且仍然可以通过#{stringTrimmer}forClass 无法应用的那些组件上将转换器作为托管bean 引用。

    <p:inputText onkeyup="PF('dataTableUIWidget').filter();" converter="#{stringTrimmer}" />
    

    【讨论】:

      【解决方案2】:

      @BalusC 的替代方法是使用帮助器“getter / setter”包装器对象将属性绑定到通用映射中,以免您的代码与样板 bean 属性混淆。

      PropertyAccessor

      public class PropertyAccessor<T> implements Serializable
      {
          // bean property path
          private String property;
      
          // value
          private T value;
      
          // getter & setter for value
      }
      

      过滤贴图

      将此地图保存在请求或视图范围的 bean 或您的“DAO”包装类中。

      private final Map<String, PropertyAccessor> filterProperties = new HashMap<>();
      
      /**
       * Get default / temporary filter property
       *
       * @param property Name of property
       * @param init Initial default value
       *
       * @return
       */
      public <T> PropertyAccessor<T> getFilterProperty(final String property, final T init)
      {
          if (!this.filterProperties.containsKey(property))
              this.filterProperties.put(property, new PropertyAccessor<T>(property, init));
      
          return this.filterProperties.get(property);
      }
      

      示例:

      具有通用 dao 和带有转换器和可选默认值的全状态过滤器的复合组件。

      <p:column headerText="Barcode" filterBy="#{tblVarProduct.barcode}>
          <f:facet name="filter">
              <p:inputText value="#{cc.attrs.dao.getFilterProperty('barcode', null).value}" 
                  converter="BarcodeConverter"
                  onchange="PF('#{tblProductWidgetVar}').filter();"/>
          </f:facet>
          <h:outputText value="#{tblVarProduct.barcode}"/>
      </p:column>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-04
        • 1970-01-01
        • 2013-08-01
        • 1970-01-01
        • 2012-11-01
        • 2014-08-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多