Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
174 views
in Technique[技术] by (71.8m points)

jsf - dynamic view injection or routing

i have a JSF projekt and in there i have different views, which are backed by ManagedBeans.

What i would like to achieve is to change some views while others stay where they are. this has to happen dynamically. In other words. I want to inject and remove views from an xhtml page without a page refresh. I have no clue how to achieve this.

Even better would be a dynamic view injection based on urls. angularjs does that very well. But even without routing it would be great.

Thanks in advance.

Here is an example in pseudo code:

<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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What you ask is better done using Facelet templating. You'll be able that way to have a page template with the shared content (the navigation menu in your case) and make the rest of the views inherit from it.

What can I see from your suggested solution is that you're abusing the POST calls. #{fragmentsPresenter.changeView('viewOne')} doesn't make sense just because you already know where you want to go to when you press that link (to viewOne), So you'll be better using plain links for that.

Here you've got an example showing how to handle navigation in a proper way. Let's suppose you've got a view controller even you won't need it in most of the cases:

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";
        }
    }
}

This controller's job is just to check what view are you coming from and switch to the other one. It's pointless to perform a POST request (to send a form) just to navigate to the other view, while you could evaluate it before page rendering.

Here you've got how the template view is built:

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>

This template page defines a shared button/link set and calls for content. I've implemented different kind of navigation options. Using <h:link /> is, in this case, the most straight-forward way. Check the second link, here we evaluate the current view id when it gets rendered and a link to go to the opposite one is created. Cool, isn't it?

Now here it is the implementation of the child views:

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>

You'll be able to type their address in your browser and see them, that's what's called bookmarkable ;-)

See also:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...