首页 > 解决方案 > 在 PrimeFaces 4.0 中没有 getter 的 p:dataTable 排序

问题描述

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

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

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

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

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

标签: primefaces

解决方案


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

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

所以

sortBy="#{bla.myAttribute}"` 

传递给 load 方法

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 对此有所帮助。


推荐阅读