Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<ui:include> with dynamic src ... complete madness [duplicate]

Tags:

jsf-2

I'm having a massive problem getting an extremely simple task done in JSF. The problem: I have objects, who have aggregated properties that can vary in type from object to object. Depending on the type of the property, I want to use a different set of input fields.

The subtype components reside in frameworks and get loaded on demand. To this end, I use the following code:

<h:panelGroup id="zusatzdaten">
    <fieldset class="clear">
    <legend>#{tickerUI.ticker.tickerDescription.label}
          (#{tickerUI.ticker.tickerDescId})
    </legend>
    <h:panelGroup rendered="#{tickerUI.editComponentName != null}">
        <ui:include src="#{tickerUI.editComponentName}"/>
    </h:panelGroup>
    </fieldset>
</h:panelGroup>

The name of the component comes out of TickerUI, which is of @SessionScope. Now the dazzling bit: when it first loads, the correct subcomponent is displayed. However, when using a link in the navigation, which should lead to including a different component, the content is NOT updated! This results in an error, because the data is now a different subtype, but the form components are still from the previous one.

When going back from the error and clicking the link again, the correct component is displayed. I logged the value of editComponentName and the correct values are returned. This is very confusing. Why is including the wrong content when the getter returns the correct component name to the 's src attribute?

Help greatly appreciated.

like image 375
Jürgen Simon Avatar asked Apr 23 '13 13:04

Jürgen Simon


2 Answers

Actually your problem is a classic view build vs view render time problem/misunderstanding. More specifically, the view is built on every new request and reconstructed from a previously saved state on postbacks. Later the view is rendered to produce HTML content.

Now, as <ui:include> is a tag handler, or in official terms a view build time tag, when you first request the page, its value attribute is evaluated, and the included page makes its way into the view. Upon postback, contrary to what you might expect, the incuded contents are already there, in the reconstructed view. So, it is an expected behaviour that you'll have the exact part of view rendered.

As to the solution, you could just simply include an exhaustive list of static includes that are wrapped in conditionally rendered <ui:fragment> JSF components. For simplicity, all content could be places within a container like <h:panelGroup> that's always rendered for ease of AJAX updates. The code could be assembled as follows:

<h:panelGroup id="ui">
    <ui:fragment rendered="#{bean.condition1}">
        <ui:include src="/path/to/file1.xhtml"/>
    </ui:fragment>
    ...
    <ui:fragment rendered="#{bean.condition_n}">
        <ui:include src="/path/to/file_n.xhtml"/>
    </ui:fragment>
</h:panelGroup>
like image 96
skuntsel Avatar answered Sep 25 '22 05:09

skuntsel


A classical dilemma, it seems. BalusC's blog gave the solution for my case in the form of a configuration parameter in web.xml:

<context-param> 
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
    <param-value>false</param-value>
</context-param>
like image 24
Jürgen Simon Avatar answered Sep 24 '22 05:09

Jürgen Simon