我想知道 JSF(或其任何框架,例如 Primefaces)是否有可能在页面中显示不同的组件顺序,或更准确地说是面板。
例如,向用户显示 3 个不同的内容部分(这些是从 1 到 3 的面板)。但是,在设置中,他应该设置这些内容部分的显示顺序(例如,panel3 应位于顶部,panel1 位于中间,panel2 位于底部)。
我想到的唯一想法是使用组件绑定(bind)或某种不可见的排序数据列表,但这些是我宁愿避免的方法,因为它涉及太多的解决方法。
最佳答案
这在 JSF 中实际上非常简单。该框架使您能够将自己插入到生命周期的不同渲染和构建事件中。例如,您可以轻松地使用此功能在渲染 View 并将其发送到浏览器之前对组件进行随机排列。
代码
这是一个包含五个 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
的位置可以看出标签,我们将自己插入 preRenderComponent
父阶段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
方法,并且在调用时只是对组件进行洗牌。如果重新加载页面,组件会重新排列。
旁注
做 shuffle()
的原因组件列表的副本上是 JSF 使用自定义 ChildrenList
基于 ArrayList
的类。实现很糟糕并导致 Collections.shuffle()
崩溃 IndexOutOfBoundsException
。这只是解决这个问题。
替代解决方案
处理此问题的另一种方法是依赖某些提供内置排序的组件或使用 h:panelGroup
上声明的绑定(bind)。成分。这将允许您根据某些设置以编程方式填充该组件。然而,这会将大部分 View 定义从 XHTML 文件移至 java 类中。如果面板中有很多子组件,事情也会稍微复杂化,如果它们彼此非常不同,事情就会变得更加复杂。以编程方式定义所有这些可能会很麻烦。
结论
就我个人而言,我更喜欢插入事件循环并仅移动或修改 XHTML 页面中已定义的组件(按照上面的代码),因为这会将更多 View 定义移动到其所属的 XHTML 文件中。
关于java - JSF 页面中组件(面板)的可变顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54189816/