具有列切换器的Primefaces数据表与列

时间:2016-09-27 06:45:52

标签: primefaces jsf-2

我有一个包含列切换器的数据表。当我取消选中某列并对某个字段进行排序时,该表是错误的。未选中字段的标题会弹回,所有数据都会向左移动,这会使1列空。

我的table.xhtml文件:

<h:form>    
    <p:dataTable id="registrations" var="registration" tableStyle="table-layout: auto;" widgetVar="registrationsTable" 
        value="#{overviewBean.listOfRegistrations}" 
        filteredValue="#{overviewBean.filteredListOfRegistrations}" emptyMessage="No registrations found with given criteria" >
        <f:facet name="header">
            <p:outputPanel style="text-align:left;">
                <h:outputText value="Search all fields: " />
                <p:inputText id="globalFilter" onkeyup="PF('registrationsTable').filter()" style="width:150px;" placeholder="Enter keyword"/>

                <p:commandButton id="toggler" type="button" value="Columns"  icon="ui-icon-calculator" style="float:right;"/>
                <p:columnToggler datasource="registrations" trigger="toggler" >
                </p:columnToggler>
            </p:outputPanel> 
        </f:facet>


        <p:column headerText="Active" visible="false">
            <h:outputText value="Y" />
        </p:column>

        <p:column headerText="Firstname" filterBy="#{registration.firstname}" filterStyle="display:none" sortBy="#{registration.firstname}">
            <h:outputText value="#{registration.firstname}" />
        </p:column>

        <p:column headerText="Lastname" filterBy="#{registration.lastname}" filterStyle="display:none" sortBy="#{registration.lastname}">
            <h:outputText value="#{registration.lastname}" />
        </p:column>

    </p:dataTable>
</h:form>

3 个答案:

答案 0 :(得分:4)

我在这篇博文中找到了答案: http://blog.primefaces.org/?p=3341

解决方案是保持支持bean中所有列的Visibility状态。

切换器必须触发辅助bean中的onToggle功能:

<p:columnToggler datasource="registrations" trigger="toggler" >
    <p:ajax event="toggle" listener="#{overviewBean.onToggle}" />
</p:columnToggler>

每个列必须由辅助bean中的布尔列表设置:

<p:column headerText="Entry date" sortBy="#{registration.entryDate}" visible="#{overviewBean.list[0]}">
    <h:outputText value="#{registration.entryDate}">
        <f:convertDateTime pattern="dd/MM/yyyy" />
    </h:outputText>
</p:column>

在支持bean中,您必须有一个布尔值列表,表示每个字段的可见性:

private List<Boolean> list;

public List<Boolean> getList() {
    return list;
}

public void setList(List<Boolean> list) {
    this.list = list;
}

public void onToggle(ToggleEvent e) {
    list.set((Integer) e.getData(), e.getVisibility() == Visibility.VISIBLE);
}

@PostConstruct方法中,您必须初始化此bean列表:

list = Arrays.asList(false, true, true);

答案 1 :(得分:2)

在Primefaces 6.1.10中,您可以使用multiViewState =&#34; true&#34;在dataTable上,与columnToggler中的ajax调用一起,您可以在没有辅助bean解决方法的情况下保存列可见性。在我的测试中,列上的排序功能不再存在冲突。

更新:使用multiViewState进行更多测试后=&#34; true&#34;在打开或关闭列之后,在排序结果时似乎仍然存在一些错误。切换到另一个页面并返回会导致正确呈现的表和列顺序。已创建问题https://github.com/primefaces/primefaces/issues/3088

增强功能实施于: https://github.com/primefaces/primefaces/issues/3044

用法是:

  configpath = 'Publisher/settings.config'
    config.read(configpath)

有关PrimeFaces中multiViewState的更多信息,请参阅TableState演示: https://www.primefaces.org/showcase/ui/data/datatable/tableState.xhtml

这包括存储排序的可能性。

新列重新排序功能: https://github.com/primefaces/primefaces/issues/3041

新列调整大小功能: https://github.com/primefaces/primefaces/issues/3046

答案 2 :(得分:2)

替代解决方案:通过继承PrimeFaces p:columnToggler来创建自己的有状态切换器。

更新:补偿了列可能将rendered属性设置为false的事实。

package my.domain;

import org.omnifaces.util.Components;
import org.primefaces.behavior.ajax.AjaxBehavior;
import org.primefaces.behavior.ajax.AjaxBehaviorListenerImpl;
import org.primefaces.component.column.Column;
import org.primefaces.component.columntoggler.ColumnToggler;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.event.ToggleEvent;
import javax.el.MethodExpression;
import javax.faces.component.FacesComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ListenerFor;
import javax.faces.event.PostAddToViewEvent;
import java.io.IOException;

@FacesComponent(
    value = StatefulColumnToggler.COMPONENT_TYPE,
    createTag = true,
    tagName = StatefulColumnToggler.TAG_NAME,
    namespace = StatefulColumnToggler.NAMESPACE
)
@ListenerFor(systemEventClass=PostAddToViewEvent.class)
public class StatefulColumnToggler extends ColumnToggler {
    public static final String TAG_NAME = "statefulColumnToggler";
    public static final String COMPONENT_TYPE = "my.domain.statefulColumnToggler";
    public static final String NAMESPACE = "http://xmlns.domain.my/jsf/component";

    public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
        super.processEvent(event);
        if (event instanceof PostAddToViewEvent) {
            // This behaviour is static, so it does not have to be in the partial state: recreate it on every request.
            AjaxBehavior ajaxBehavior = (AjaxBehavior) getFacesContext().getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
            MethodExpression methodExpression = Components.createMethodExpression("#{component.onToggleHandler}", null, new Class<?>[]{ToggleEvent.class});
            ajaxBehavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(methodExpression, methodExpression));
            addClientBehavior("toggle", ajaxBehavior);
        }
    }

    public void onToggleHandler(ToggleEvent toggleEvent) {
        final DataTable dataTable = (DataTable) this.getDataSourceComponent();
        final int clientColumnIndex = (Integer) toggleEvent.getData();
        // Compensate for columns that are on the server, but not in the client.
        int columnsNotInClient = 0;
        for (int serverColumnIndex = 0; ; serverColumnIndex++) {
            if (serverColumnIndex >= dataTable.getColumns().size()) {
                throw new IllegalArgumentException("received index " + clientColumnIndex + " from client, but there is no rendered server side column with that index");
            }
            Column column = (Column) dataTable.getColumns().get(serverColumnIndex);
            if (!column.isRendered()) {
                columnsNotInClient++;
            }
            if (serverColumnIndex - columnsNotInClient == clientColumnIndex) {
                 column.setVisible(!column.isVisible());
                // Must delete any 'user' specified value expression, or it will take precedence over the toggled value.
                 column.setValueExpression(Column.PropertyKeys.visible.name(), null);
                break;
            }
        }
    }
}

声明命名空间

xmlns:my=http://xmlns.domain.my/jsf/component

并将其添加到页面中。

<my:statefulColumnToggler datasource="table_id" trigger="button_id" />