我有一个JSF项目,在那里我有不同的视图,这些视图由ManagedBeans支持。
我想要达到的是改变一些观点,而另一些人保持不变。这必须动态地发生。换句话说。我想在不刷新页面的情况下从xhtml页面注入和删除视图。我不知道如何做到这一点。
基于url的动态视图注入会更好。Angularjs在这方面做得很好。但即使没有路由,它也会很棒。
提前感谢。
下面是一个伪代码示例:
<nav>
<h:link action="navigationBean.changeView(view1)" method="ajax">Link1</h:link>
<h:link action="navigationBean.changeView(view2)" method="ajax">Link2</h:link>
</nav>
<h:viewContainer>
// view selected by clicking the nav links should be injected here without page reload
</h:viewContainer>
您的问题最好使用Facelet模板完成。您将能够以这种方式拥有具有共享内容的页面模板(在您的示例中是导航菜单),并使其他视图继承自它。
从您建议的解决方案中我可以看出,您正在滥用POST调用。#{fragmentsPresenter.changeView('viewOne')}
没有意义,只是因为你已经知道你想去哪里,当你按下链接(到viewOne
),所以你会更好地使用普通链接。
这里有一个示例,展示了如何以适当的方式处理导航。让我们假设你有一个视图控制器,即使你在大多数情况下都不需要它:
ViewController.java
/**
* Give the scope you want to your bean depending on what are your operations
* oriented to. This example could be @ApplicationScoped as well
*
* @author amaeztu
*
*/
@ManagedBean
@SessionScoped
public class ViewController {
/**
* Just gets the current view path and switches to the other one
*
* @return
*/
public String changeView() {
String viewId = FacesContext.getCurrentInstance().getViewRoot()
.getViewId();
if (viewId.equals("/view1.xhtml")) {
return "/view2";
} else {
return "/view1";
}
}
}
这个控制器的工作只是检查你来自哪个视图并切换到另一个视图。执行POST请求(发送表单)只是为了导航到另一个视图是没有意义的,而您可以在页面呈现之前对其进行评估。
你已经知道了模板视图是如何构建的:
template.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head />
<h:body>
<h:form>
<!-- Use POST requests like this only when you have
to determine the destination dinamically at server side -->
<h:commandButton value="Switch View with POST"
action="#{viewController.changeView}" />
<br />
</h:form>
<!-- For plain navigation, use GET requests -->
<h:link value="Go to view 1" outcome="/view1" />
<br />
<!-- Determine where we are at page rendering time
and evaluate the other view path -->
<h:link value="Switch view without POST"
outcome="#{view.viewId eq '/view1.xhtml' ? '/view2' : '/view1'}" />
<br />
<br />
<ui:insert name="content" />
</h:body>
</ui:composition>
这个模板页定义了一个共享按钮/链接集,并调用内容。我实现了不同类型的导航选项。在这种情况下,使用<h:link />
是最直接的方法。检查第二个链接,这里我们评估当前视图id,当它被渲染和链接到相反的一个被创建。很酷,不是吗?
现在它是子视图的实现:
view1.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" template="/template.xhtml">
<ui:define name="content">
<!-- Here you could have some @ViewScoped
bean managing the content i.e. #{view1Bean} -->
View 1
</ui:define>
</ui:composition>
view2.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" template="/template.xhtml">
<ui:define name="content">
View 2
</ui:define>
</ui:composition>
你可以在浏览器中输入他们的地址并看到他们,这就是所谓的bookmarkable;-)
参见:
- 以编程方式获取当前页面
好的,我是这样解决的:
我的观点:
<h:body>
<nav>
<h:form>
<h:commandLink action="#{fragmentsPresenter.changeView('viewOne')}">
viewOne
<f:ajax execute="@this" render="fragment-container" />
</h:commandLink>
<h:commandLink action="#{fragmentsPresenter.changeView('viewTwo')}">
viewTwo
<f:ajax execute="@this" render="fragment-container" />
</h:commandLink>
</h:form>
</nav>
<h:panelGroup id="fragment-container">
<ui:fragment rendered="#{fragmentsPresenter.activeView('viewOne')}">
<div>i am view one!</div>
</ui:fragment>
<ui:fragment rendered="#{fragmentsPresenter.activeView('viewTwo')}">
<div>i am view Two!</div>
<ui:include src="fragment.xhtml"/>
</ui:fragment>
</h:panelGroup>
和ManagedBean:
@ManagedBean
@SessionScoped
public class FragmentsPresenter {
private String activeView;
public void setActiveView(String viewName) { this.activeView = viewName; }
public String getActiveView() { return this.activeView; }
public FragmentsPresenter() { this.activeView = "viewOne"; }
public void changeView(String viewName) { this.activeView = viewName; }
public boolean activeView(String viewName) {
return activeView.equals(viewName);
}
}