当在左侧部分中选择菜单项时,我需要在主要内容部分中动态加载 xhtml 页面,从而避免页面刷新。
我在左侧创建了一个 Prime Faces 动态面板菜单,其中包含子菜单列表和每个子菜单的菜单项。菜单根据登录用户的角色动态加载。选择菜单项时,会调用相应的 Action Listener,但不会加载或显示页面
该应用程序正在使用 Prime Faces 3.4.1 / JSP 2.0 / Spring Framework 3.1.1 开发
有关应用程序背景的更多信息
屏幕布局分为四个部分。
页眉 - 所有通用的徽标和图标 页脚 - 包含页脚信息 左侧栏 - 包含菜单。这是根据登录用户的角色动态填充的 Main Content - 这会在左侧显示对应于所选菜单项的实际 .xhtml 页面
我使用 Facelet 模板来定义布局和内容。以下是定义的模板
布局模板.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
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>RF</title>
<link type="text/css" rel="stylesheet" href="# {facesContext.externalContext.requestContextPath}/javax.faces.resource/main.css.xhtml?ln=css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<f:view contentType="text/html; charset=UTF-8" encoding="UTF-8" >
<div id="outerWrapper">
<div id="pageHeader">
<ui:insert name="pageHeader">
</ui:insert>
</div>
<div id="contentWrapper">
<div id="leftPanel">
<div class="jsmenu">
<ui:insert name="leftPanel">
</ui:insert>
</div>
</div>
<div id="mainContent">
<div id="mainStyle">
<h:panelGroup id="mainOutputPanel">
<h:form id="mainContentForm">
<ui:insert name="mainContent">
</ui:insert>
</h:form>
</h:panelGroup>
</div>
</div>
<div class="clearFloat"></div>
</div>
<div id="footer">
<ui:insert name="footer">
</ui:insert>
</div>
</div>
</f:view>
</h:body>
</html>
主屏幕布局
以下是包含上面定义的模板的主屏幕布局。我已经包含了 header.xhtml、footer.xhtml 和 rfleft.xhtml,其中包含动态填充的菜单。在 中,我正在获取要从 JSF 支持 bean 加载的页面
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<ui:composition template="/pages/protected/templates/layoutTemplate.xhtml">
<ui:define name="pageHeader">
<ui:include src="/pages/protected/templates/loginHeader.xhtml">
</ui:include>
</ui:define>
<ui:define name="leftPanel">
<ui:include src="/pages/protected/templates/rfleft.xhtml">
</ui:include>
</ui:define>
<ui:define name="mainContent">
<ui:include id="mainPage" src="#{menuMB.screenName}">
</ui:include>
</ui:define>
<ui:define name="footer">
<ui:include src="/pages/protected/templates/footer.xhtml">
</ui:include>
</ui:define>
</ui:composition>
</h:body>
</html>
左菜单动态加载菜单 (rfleft.xhtml)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:body>
<h:form id="leftMainForm">
<p:panelMenu style="width:200px" model="#{menuMB.mnuModel}">
</p:panelMenu>
</h:form>
</h:body>
</html>
JSF 支持 Bean
@SessionScoped
@ManagedBean(name = "menuMB")
public class MenuMB implements Serializable {
@ManagedProperty(value = "#{LoginService}")
ILoginService loginService;
private String screenName = "";
String menuUrl = "";
User loggedUser = null;
private List<FunctionMaster> fmList = null;
private MenuModel mnuModel = new DefaultMenuModel();
public MenuMB() {
loggedUser = (User) RFContextUtil.getSessionFromContext("user");
}
@PostConstruct
public void loadMenu() {
if (loggedUser != null) {
//Load the actions to be performed by the logged user . Loading as menu item
fmList = loginService.getMenuForUser(loggedUser.getUserID());
}
createMenu(fmList);
}
private void createMenu(List<FunctionMaster> fmList) {
try {
if (fmList != null) {
for (FunctionMaster sub : fmList) {
if (sub.getParentFunctionID() == 0) {
Submenu rfSubMenu = new Submenu();
rfSubMenu.setLabel(sub.getScreenDisplayName());
getMnuModel().addSubmenu(rfSubMenu);
for (FunctionMaster item : fmList) {
if (item.getParentFunctionID() != 0) {
if (item.getParentFunctionID() == sub.getFunctionID()) {
MenuItem rfSubItem = new MenuItem();
rfSubItem.setId(item.getFunctionName() + item.getFunctionID().toString());
rfSubItem.setValue(item.getScreenDisplayName());
rfSubItem.setImmediate(true);
rfSubItem.setProcess("@form");
rfSubItem.setPartialSubmit(true);
rfSubItem.setUpdate(":mainOutputPanel");
rfSubItem.setAjax(true);
rfSubItem.setRendered(true);
//Adding Action Listener
ExpressionFactory factory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
MethodExpression methodExpr = factory.createMethodExpression(FacesContext.getCurrentInstance().getELContext(), "#{menuMB.loadScreenFromMenu}", Void.class, new Class[]{ActionEvent.class});
MethodExpressionActionListener actionListener = new MethodExpressionActionListener(methodExpr);
rfSubItem.addActionListener(actionListener);
rfSubMenu.getChildren().add(rfSubItem);
}
}
}
}
}
}
} catch (Exception ex) {
String excep = ex.getMessage();
}
}
public void loadScreenFromMenu(ActionEvent event) {
MenuItem menuItem = (MenuItem) event.getComponent();
String attrName;
try {
if (menuItem != null) {
screenName = RequestFactoryContextUtil.getResourceBundleString(menuItem.getId());
//Set the screen that needs to be displayed. This is the property that is used in the Main Screen layout
setScreenName(screenName);
}
} catch (Exception exc) {
}
}
}
任何帮助表示赞赏。
-巴斯卡