【问题标题】:p:dataTable sorting without getters in PrimeFaces 4.0在 PrimeFaces 4.0 中没有 getter 的 p:dataTable 排序
【发布时间】:2018-07-17 17:45:07
【问题描述】:

我有一个显示数据的数据表,但排序不起作用。

问题是,这些记录没有getFieldName getter,而是getValue('FieldName')。这使我可以在不重新编译的情况下更改架构。

例如,一个这样的字段是日期。

我想要一些技巧来使这段代码工作,而不必为每个表创建自定义 bean,因此与物理数据模型紧密耦合。

                    <p:column headerText="Date" sortBy="#{r.getValue('date')}">
                        <h:outputText value="#{r.getValue('date')}" />
                    </p:column>

【问题讨论】:

  • 我认为最好切换到lazyLoading并在sortBy或其他一些被剥离并仅返回“日期”的假EL中声明#{bla.date}
  • 对于bla.date,bla需要实现一个getDate()方法,对吧?如果是这样,这就是我想避免的。数据访问层不知道应用层表的字段名称。因此,如果不为每个数据库表或视图创建特定的 bean,我就无法拥有一个可排序的表。
  • 不,它没有 iirc... 第一部分被剥离,在lazyDataModel 的加载方法中,只有日期被传递。 'bla' 可以是任何东西(至少可以是)。
  • 如果你能写一些示例代码......但我会研究延迟加载,谢谢!
  • 这一切都在 PrimeFaces 手册中,展示(记得使用两者的 4.0 版本)PrimeFaces 论坛和 stackoverflow 以及互联网的其余部分......如果你有实际的编码问题,我愿意提供帮助。

标签: primefaces


【解决方案1】:

您希望它的工作方式不是它在p:dataTable 中的工作方式。我不确定普通的直接(非延迟)过滤是如何工作的。我从来没有使用过它,我总是 implement lazy loading 有很多基类,所以它很容易为不同的实体等实现,并让我完全控制(OptimusFaces 在这里有帮助)

对于 LazyDataModel,您需要放置“EL”的sortBy 属性并未真正评估为 EL。不在 6.2 中,但 iirc 也不在 4.0 中。事实上,你放在那里的 EL 被删除了 `#{..} 并在预期的点上分割。生成的部分将传递给过滤器属性中的 load 方法。

所以

sortBy="#{bla.myAttribute}"` 

作为

传递给加载方法
myAttribute 

可以在展示中的 LazyDataModel.java 中看到(顺便说一句,过滤也是如此)。

@Override
public List<Car> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
    List<Car> data = new ArrayList<Car>();

    //filter
    for(Car car : datasource) {
        boolean match = true;

        if (filters != null) {
            for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                try {
                    String filterProperty = it.next();
                    Object filterValue = filters.get(filterProperty);
                    String fieldValue = String.valueOf(car.getClass().getField(filterProperty).get(car));

                    if(filterValue == null || fieldValue.startsWith(filterValue.toString())) {
                        match = true;
                }
                else {
                        match = false;
                        break;
                    }
                } catch(Exception e) {
                    match = false;
                }
            }
        }

        if(match) {
            data.add(car);
        }
    }

    //sort
    if(sortField != null) {
        Collections.sort(data, new LazySorter(sortField, sortOrder));
    }

    //rowCount
    int dataSize = data.size();
    this.setRowCount(dataSize);

    //paginate
    if(dataSize > pageSize) {
        try {
            return data.subList(first, first + pageSize);
        }
        catch(IndexOutOfBoundsException e) {
            return data.subList(first, first + (dataSize % pageSize));
        }
    }
    else {
        return data;
    }
}

(在 LazySorter 中,在“Car”类上使用与过滤相同的反射:Car.class.getField(sortField).get(...),这意味着“EL”中的整个第一部分都被剥离了。因此你可以放任何前面是假货。

这使得完全可以做你想做的事,而不是

sortBy="#{r.getValue('date')}"

随便用

sortBy="#{myFakePrependeSomething.date}"

如果你想对对象的某个字段进行排序,请使用

sortBy="#{myFakePrependeSomething.item.date}"

然后传入“item.date”,您只需进行反射以首先获取“item”字段,然后获取日期。 OptimusFaces 对此有所帮助。

【讨论】:

    【解决方案2】:

    我无法引入 OptimusFaces,所以我必须在 LazySorter 的比较方法中进行:

    说清楚:这与 primefaces 提供的示例比较方法开箱即用:

         <p:column headerText="Id" sortable="true" sortBy="#{obj.id}" filterable="true" filterMatchMode="contains" filterBy="#{obj.id}">
                <h:outputText value="#{obj.id}"></h:outputText>
            </p:column>
    

    这不是:

     <p:column headerText="Vorname" sortable="true" sortBy="#{obj.person.vorname}" filterable="true" filterMatchMode="contains" filterBy="#{obj.person.vorname}">
                <h:outputText value="#{obj.person.vorname }"></h:outputText>
            </p:column>
    

    因为传递给比较器的 sortField 是“obj.person.vorname”,而示例方法只找到父对象的字段,如下所示:

      Field[] userFields = Obj.class.getDeclaredFields();
             for (Field field : objFields) {
    
                 if (field.getName().equals(sortField)) {
                     field.setAccessible(true);
                     value1 = field.get(cp1);
                     value2 = field.get(cp2);
                 }
             }...
    

    所以要获取孩子的字段,

     if(sortField.contains("person.")){
             Field[] personFields = Personen.class.getDeclaredFields();
             String pSortField = sortField.substring(7, sortField.length());
    
             for(Field pField : personFields){
                 if(pField.getName().equals(pSortField)){
                     pField.setAccessible(true);
                     value1 = pField.get(cp1.getPerson());
                     value2 = pField.get(cp2.getPerson());
                 }
             }
         }
         else if(... do it like bevore ....
    

    也许有人可以提供一种更“反思”的方式,这里使用“substing”让我很困扰......更通用的方法会很好......

    顺便说一句。现在是 primefaces 8

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-14
      • 2011-07-24
      • 2013-02-03
      • 1970-01-01
      • 2013-08-09
      相关资源
      最近更新 更多