我想使用Primefaces组件向我的网络应用添加动态面包屑。我已经创建了一个模型来推送痕迹上的项目,以便在遵循其中一个链接时删除尾随链接。这适用于大多数情况,但有时bradcrumb的行为与我的预期不同。基本上,为了跟踪登录页面,我在每个可导航页面上添加了一个preRenderView
侦听器,并在会话范围的bean中实现了模型更新逻辑。
<f:event type="preRenderView" listener="#{bcb.onRenderView}" />
<f:attribute name="pageName" value="ThisPage" />
侦听器接收页面名称作为属性,并从外部上下文获取完整的URL(包括查询字符串);这些信息以及从UIViewRoot
创建的唯一ID用于构建推送到模型上的BreadCrumbItem
:
public void onRenderView(ComponentSystemEvent evt) {
UIViewRoot root = (UIViewRoot)evt.getSource();
final String reqUrl = FacesUtils.getFullRequestURL();
String pageName = (String) evt.getComponent().getAttributes().get("pageName");
if(pageName != null) {
model.push(new BreadCrumbItem(root.createUniqueId(), pageName, reqUrl));
} else {
model.reset();
}
}
模型的push()
和reset()
方法实现如下:
/**
* When a link is pushed on the bread crumb, the existing items are analyzed
* and if one is found to be equal to the pushed one, the link is not added
* and all the subsequent links are removed from the list.
*
* @param link
* the link to be added to the bread crumb
*/
public void push(BreadCrumbItem link) {
boolean found = removeTrailing(link);
if(!found) {
addMenuItem(link);
}
}
/**
* Reset the model to its initial state. Only the home link is retained.
*/
public void reset() {
BreadCrumbItem home = new BreadCrumbItem();
removeTrailing(home);
}
这种方法可行吗?您是否可以建议一些更好的方法来跟踪页面导航而无需利用生命周期监听器?非常感谢你的帮助。
答案 0 :(得分:3)
我为我的网络应用程序实现了自己的一个,在我的情况下,我没有使用p:breadCrumb
组件,因为它是使用按钮实现的。
基本上,我有一个@SessionScoped
bean,它包含一个堆栈(导航堆栈),存储你在痕迹中的所有url以及每个url的params。视图( xhtml )部分由p:button
个元素组成,这些元素具有堆栈存储的网址的outcome
。
当你导航到 url 时,会调用相应的bean f:event type="preRenderView"
(就像你正在做的那样)并且bean从url中获取params,之后它建立了本身进入堆栈(不是bean本身,导致它@ViewScoped
并将被破坏,只是url和params。)
如果单击breadcrum中的后退按钮,则会发送另一个参数,指示按钮的 index 。基于该索引,目标bean知道您正在尝试恢复此类视图,因此请求该视图的导航堆栈参数和导航堆栈将删除其后的navegable。
我花了一段时间,但它功能齐全。祝你好运。
修改强>
使用会话范围保存当前导航状态时要小心。它会对所有打开的选项卡产生影响,因此可能不是您想要的,除非您希望最终用户仅在一个选项卡中使用您的应用程序。无论如何,一般的可用性指南说你应该使用类别而不是导航路径来获取面包屑(HTTP is stateless,并且历史本身由浏览器保存)。 因此,动态面包屑不再有意义了,至少如果您使用不同的网址进行观看。