动态视图注入或路由



我有一个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);
    }
}

最新更新