我有一个提供数据的数据表,但排序不起作用。
问题是,这些记录没有getFieldName getter,但是有getValue('FieldName')。这使我无需重新编译即可更改架构。
例如,一个这样的字段是日期。
我想要一些技巧来使此代码有效,而不必为每个表创建自定义bean,从而与物理数据模型紧密耦合。
<p:column headerText="Date" sortBy="#{r.getValue('date')}">
<h:outputText value="#{r.getValue('date')}" />
</p:column>
答案 0 :(得分:2)
您希望它工作的方式与p:dataTable
中的工作方式无关。我不确定普通直接(非延迟)过滤的工作方式。我从未使用过它,并且我总是implement lazy loading使用很多基类,因此很容易为不同的实体等实现,并为我提供了完全的控制权(OptimusFaces在这里提供帮助)
对于LazyDataModel,您需要在其中放置“ EL”的sortBy
属性并未真正评估为EL。不在6.2中,但iirc也未在4.0中。实际上,您在其中放置的EL带有“#{..}”标记,并在此处期望的点上分开。生成的零件将在过滤器属性中传递给load方法。
所以
sortBy="#{bla.myAttribute}"`
作为
传递给load方法。myAttribute
在展示柜中的LazyDataModel.java中可以看到(对于过滤btw同样如此)。
@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.class.getField(sortField).get(...)
,这意味着“ EL”中的整个第一部分被剥离了。因此,您可以放在假货前面。
这使您可以完全按照自己的意愿去做,而不是
sortBy="#{r.getValue('date')}"
只需使用
sortBy="#{myFakePrependeSomething.date}"
如果要对对象的字段进行排序,请使用
sortBy="#{myFakePrependeSomething.item.date}"
,然后传入“ item.date”,您只需要进行反射即可首先获取“ item”字段,然后获取日期。 OptimusFaces可以帮助您。
答案 1 :(得分:0)
我无法引入 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”,而 samplemethod 只找到父对象的字段,如下所示:
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