我想知道JSF(或其任何框架,例如Primefaces)是否有可能在页面中显示可变的组件顺序,或更确切地说是面板。
>例如,向用户显示3个不同的内容部分(从1到3的面板)。但是,在设置中,他应该设置这些内容部分的显示顺序(例如,panel3应该在顶部,panel1在中间,panel2在底部)。
我想到的唯一想法是使用组件绑定或某种不可见的排序数据列表,但是我宁愿避免使用这些方法,因为它涉及太多解决方法。
答案 0 :(得分:3)
这实际上在JSF中非常简单。该框架使您能够将自己插入不同的渲染并构建生命周期的事件。因此,例如,您可以轻松地使用此功能在呈现视图并将其发送到浏览器之前对组件进行随机播放。
这里是一个XHTML页面的示例,其中定义了五个p:panel
组件。每次您重新加载页面时,组件都会被随机排列并以不同的顺序显示。您可以轻松地对此进行调整,以按照您喜欢的顺序或根据某些配置设置显示它们;
<?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
的{{1}}阶段。这样,我们可以在该组件的呈现阶段开始之前接收事件。
h:panelGroup
上面的后备bean定义了@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);
}
}
方法,并且在调用时只是将周围的组件改组。如果您重新加载页面,则组件将重新组合。
在组件列表的副本上执行onShuffle
的原因是JSF使用基于shuffle()
的自定义ChildrenList
类。该实现被破坏,并导致ArrayList
因Collections.shuffle()
而崩溃。可以解决该问题。
处理此问题的另一种方法是依赖提供内置排序的某些组件或使用在IndexOutOfBoundsException
组件上声明的绑定。这将允许您基于某些设置以编程方式填充此组件。但是,这会将大部分视图定义移出XHTML文件并移至Java类。如果您的面板中有很多子组件,那么这也会使事情稍微复杂化,并且如果它们彼此非常不同,则会使事情变得更加复杂。以编程方式定义所有内容可能很麻烦。
个人而言,我更喜欢插入事件周期,而只是移动或修改XHTML页面中已经定义的组件(按照上面的代码),因为这会将更多视图定义移动到它所属的XHTML文件中。>