本文介绍了Primefaces对包含输入的行进行重新排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一栏中有p:dataTablep:inputText:

<h:form id="form">
    <p:dataTable id="dataTable" value="#{rowReorder.dataList}"
                 var="row" draggableRows="true" rowKey="#{row.id}">
        <p:ajax event="rowReorder" listener="#{rowReorder.reorder}" update="dataTable"/>

        <p:column>
            <f:facet name="header">
                <p:commandButton value="Add" actionListener="#{rowReorder.addData}"
                                 update="dataTable" process="dataTable"/>
            </f:facet>
            <p:outputLabel value="#{row.id}"/>
        </p:column>
        <p:column>
            <p:inputText value="#{row.name}"/>
        </p:column>
    </p:dataTable>
</h:form>

后备豆:

import org.omnifaces.cdi.ViewScoped;
import org.primefaces.event.ReorderEvent;
import javax.inject.Named;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

@Named("rowReorder")
@ViewScoped
public class RowReorder implements Serializable {

    private List<Data> dataList = new LinkedList<>();

    public void addData() {
        Data data = new Data();
        data.setId(dataList.size() + 1);
        data.setName("Data " + data.getId());
        dataList.add(data);
    }

    public void reorder(ReorderEvent event) {

    }

    /**
     * Getters, Setters
     */

    public List<Data> getDataList() {
        return dataList;
    }
}

数据类:

public class Data implements Serializable {

    private Integer id;
    private String name;

    /**
     * Getters, Setters
     */

}

重新排序之前对数据表进行采样:

Sample datatable before reordering:

--------------
|id |  name  |
--------------
| 1 | Data 1 |
| 2 | Data 2 |
| 3 | Data 3 |
| 4 | Data 4 |
--------------

以及重新排序后(将第一行移至第三行):

and after reordering (moving 1-st row to 3-rd):

--------------
|id |  name  |
--------------
| 2 | Data 1 |
| 3 | Data 2 |
| 1 | Data 3 |
| 4 | Data 4 |
--------------

我知道这是因为在UPDATE_MODEL阶段从p:inputText设置数据的原因.我试图通过在p:ajax组件中指定process="@none"来防止输入字段的处理,但是它不起作用.有任何想法如何结识draggableRowsp:inputText朋友吗?

I understand that it is happening 'cause of setting data from p:inputText's at UPDATE_MODEL phase. I tried to prevent processing of input fields by specifying process="@none" in p:ajax component, but it doesn't work. Have any idea how to make draggableRows and p:inputText friends?

推荐答案

第一个解决方案

我找到了解决方案!它不处理具有属性process="@none" partialSubmit="true"

First solution

I found a solution!It does not processing inputs (and actually does not submit it at all) with attributes process="@none" partialSubmit="true"

因此完整的p:ajax组件看起来像<p:ajax event="rowReorder" listener="#{rowReorder.reorder}" update="dataTable" process="@none" partialSubmit="true"/>

So complete p:ajax component looks like<p:ajax event="rowReorder" listener="#{rowReorder.reorder}" update="dataTable" process="@none" partialSubmit="true"/>

让我们看看拖动行时发生了什么?我们有一个强制执行process="form:dataTable"的ajax请求.在APPLY_REQUEST_VALUES上,阶段DataTableRenderer尝试调用DraggableRowsFeature的解码,从而依次旋转列表元素(指定为dataTable的value属性的列表).因此,在UPDATE_MODEL_VALUES阶段,我们有一个轮换列表和输入组件,它们希望将其值提交到Data对象的name字段.但是请求参数仍然在输入ID中包含旧的行索引:它们是form:dataTable:1:name = Data 2form:dataTable:2:name = Data 3form:dataTable:0:name = Data 1(我添加了3行,并将第一行移至最后一行).因此,在这里我们得到了我们得到的.这样,如果我们需要在正确的位置提交数据,则必须防止列表在UPDATE_MODEL_VALUES完成之前旋转,并稍后在INVOKE_APPLICATION阶段执行此轮换,并在该ajax请求上呈现dataTable:

Lets check out what is happening on dragging row?We have ajax request forcing process="form:dataTable". On APPLY_REQUEST_VALUES phase DataTableRenderer tries to invoke decode of DraggableRowsFeature which, in turn, rotating list elements (list that specified as dataTable's value attribute). So on UPDATE_MODEL_VALUES phase we have a rotated list, and input components, which wants to submit their values to name fields of Data objects. But request parameters still contains old row indexes in input ids: they are form:dataTable:1:name = Data 2, form:dataTable:2:name = Data 3, form:dataTable:0:name = Data 1 (i added 3 rows, and moved first row to last). So here we getting what we got. In this way if we need data to be submitted on right places we have to prevent our list rotating before UPDATE_MODEL_VALUES is done,and perform this rotation later on INVOKE_APPLICATION phase, and render dataTable on that ajax request:

DraggableRowsFeature.decode()中,我们可以看到Collections.rotate()仅在value是List的实例时在调用.

In DraggableRowsFeature.decode() we can see that Collections.rotate() is calling only when value is instance of List.

    if (value instanceof List) {
        List list = (List) value;

        if(toIndex >= fromIndex) {
            Collections.rotate(list.subList(fromIndex, toIndex + 1), -1);
        }
        else {
            Collections.rotate(list.subList(toIndex, fromIndex + 1), 1);
        }
    }
    else {
        LOGGER.info("Row reordering is only available for list backed datatables, use rowReorder ajax behavior with listener for manual handling of model update.");
    }

还有DraggableRowsFeature.shouldDecode()方法.

public boolean shouldDecode(FacesContext context, DataTable table) {
    return context.getExternalContext().getRequestParameterMap().containsKey(table.getClientId(context) + "_rowreorder");
}

因此,在这里我们有两种防止数据源旋转的可能性:

So here we have 2 possibilities to prevent datasource rotating:

  1. 请勿使用List作为dataTable值
  2. 创建自己的org.primefaces.component.datatable.feature.DraggableRowsFeature,并在shouldDecode()方法中返回false.
  1. Don't use List as dataTable value
  2. Create own org.primefaces.component.datatable.feature.DraggableRowsFeature returning false in shouldDecode() method.

实践:

我这样修改了bean文件:

Practice:

I modified bean file like this:

@Named("rowReorder")
@ViewScoped
public class RowReorder implements Serializable {

    private static final Logger log = LoggerFactory.getLogger(RowReorder.class);
    private Set<Data> dataList = new LinkedHashSet<>();


    public void addData() {
        Data data = new Data();
        data.setId(dataList.size() + 1);
        data.setName("Data " + data.getId());
        dataList.add(data);
        log.warn("{} {}", Integer.toHexString(data.hashCode()), data.getId());
    }

    public void removeData(Data data) {
        dataList.remove(data);
    }

    public void reorder(ReorderEvent event) {
        List<Data> list = new LinkedList<>(dataList);

        int fromIndex = event.getFromIndex();
        int toIndex = event.getToIndex();
        if(toIndex >= fromIndex) {
            Collections.rotate(list.subList(fromIndex, toIndex + 1), -1);
        }
        else {
            Collections.rotate(list.subList(toIndex, fromIndex + 1), 1);
        }
        dataList.clear();
        dataList.addAll(list);
    }

    /**
     * Getters, Setters
     */

    public Set<Data> getDataList() {
        return dataList;
    }
}

现在,它首先在INVOKE_APPLICATION阶段将值提交到模型和循环列表.

And now it firstly submitting values to model and rotating list on INVOKE_APPLICATION phase.

这篇关于Primefaces对包含输入的行进行重新排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 22:20