首页 > 解决方案 > JSF 页面中组件(面板)的可变顺序

问题描述

我想知道在 JSF(或其任何框架,例如 Primefaces)中是否有可能具有将在页面中显示的组件或更准确地说是面板的可变顺序。

例如,向用户显示 3 个不同的内容部分(这些是从 1 到 3 的面板)。但是,在设置中,他应该设置这些内容部分的显示顺序(例如,panel3 应该在顶部,panel1 在中间,panel2 在底部)。

我想到的唯一想法是使用组件绑定或某种不可见的排序数据列表,但这些是我宁愿避免的方法,因为它涉及太多变通方法。

标签: javajsfprimefaces

解决方案


这在 JSF中实际上很容易。该框架使您能够将自己插入生命周期的不同渲染和构建事件中。因此,例如,您可以轻松地使用此功能在视图呈现并发送到浏览器之前对组件进行洗牌。

编码

这是一个p:panel定义了五个组件的 XHTML 页面示例。每次重新加载页面时,组件都会被打乱并以不同的顺序显示。您可以轻松地调整它以按照您喜欢的顺序或根据某些配置设置显示它们;

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui" xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Shuffle test</title>
    </h:head>
    <h:body>
        <h:panelGroup>
            <p:panel header="First"/>
            <p:panel header="Second"/>
            <p:panel header="Third"/>
            <p:panel header="Fourth"/>
            <p:panel header="Fifth"/>
            <f:event listener="#{shuffleBackingBean.onShuffle}" type="preRenderComponent" />
        </h:panelGroup>
    </h:body>
</html>

f:event标签的位置可以看出,我们将自己插入到preRenderComponentparent 的阶段h:panelGroup。这允许我们在该组件的渲染阶段之前接收事件。

@Named
@ViewScoped
public class ShuffleBackingBean implements Serializable {
    public void onShuffle(ComponentSystemEvent event) {
        final List<UIComponent> components = new ArrayList<>(event.getComponent().getChildren());
        Collections.shuffle(components);

        event.getComponent().getChildren().clear();
        event.getComponent().getChildren().addAll(components);  
    }
}

上面的支持 bean 定义了onShuffle方法,并且在调用时只是随机播放组件。如果您重新加载页面,组件会重新洗牌。

边注

对组件列表的副本执行 a 的原因shuffle()是 JSF 使用了一个ChildrenList基于ArrayList. 该实现是拙劣的,并导致Collections.shuffle()IndexOutOfBoundsException. 这只是解决这个问题。

替代解决方案

处理这个问题的另一种方法是依赖某些提供内置排序的组件或使用在h:panelGroup组件上声明的绑定。这将允许您根据某些设置以编程方式填充此组件。但是,这会将大部分视图定义从 XHTML 文件中移出到 java 类中。如果您的面板中有很多子组件,它也会使事情稍微复杂化,如果它们彼此非常不同,则会使事情变得更加复杂。以编程方式定义所有这些可能非常麻烦。

结论

就个人而言,我更喜欢插入事件循环并仅移动或修改已在 XHTML 页面中定义的组件(根据上面的代码),因为这会将更多的视图定义移动到它所属的 XHTML 文件中。


推荐阅读