2013-04-23 3 views
9

Ich habe ein großes Problem, eine sehr einfache Aufgabe in JSF getan. Das Problem: Ich habe Objekte, die Eigenschaften aggregiert haben, die vom Typ zum Objekt variieren können. Abhängig vom Typ der Eigenschaft möchte ich einen anderen Satz von Eingabefeldern verwenden.<ui:include> mit dynamischen src ... komplette Wahnsinn

Die Subtypenkomponenten befinden sich in Frameworks und werden bei Bedarf geladen. Zu diesem Zweck verwende ich den folgenden 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> 

Der Name der Komponente kommt aus TickerUI, die von @SessionScope ist. Jetzt das schillernde Bit: Beim ersten Laden wird die richtige Teilkomponente angezeigt. Wenn Sie jedoch einen Link in der Navigation verwenden, der zu einer anderen Komponente führen soll, wird der Inhalt NICHT aktualisiert! Dies führt zu einem Fehler, da die Daten jetzt einen anderen Subtyp haben, aber die Formularkomponenten immer noch von der vorherigen stammen.

Wenn Sie von dem Fehler zurückkommen und erneut auf den Link klicken, wird die korrekte Komponente angezeigt. Ich habe den Wert von editComponentName protokolliert und die richtigen Werte zurückgegeben. Das ist sehr verwirrend. Warum wird der falsche Inhalt eingefügt, wenn der Getter den korrekten Komponentennamen an das src-Attribut zurückgibt?

Hilfe sehr geschätzt.

+3

'' läuft während Ansicht Bauzeit, während Ansicht Zeit machen. Siehe auch http://stackoverflow.com/questions/3342984/jstl-in-jsf2-facelets-makes-sense – BalusC

+0

Vielen Dank. Ich bin natürlich noch neu in JSF und dieses JSTL/JSF Render-Zeug ist nicht einfach zu verstehen. Ich fand die Lösung auf Ihrem Blog: ' javax.faces.PARTIAL_STATE_SAVING false ' –

Antwort

7

Eigentlich ist Ihr Problem eine klassische Ansicht Build vs Ansicht Renderzeit Problem/Missverständnis. Genauer gesagt ist die Ansicht bei jeder neuen Anfrage gebaut und rekonstruiert aus einem zuvor gespeicherten Zustand auf Postbacks. Später ist die Ansicht gerendert HTML-Inhalt zu produzieren.

Jetzt, da <ui:include> ist ein Tag-Handler oder in allgemeinen eine Ansicht Kompilierzeit Tag, wenn Sie zum ersten Anfrage die Seite, seine value Attribut ausgewertet wird, und die darin enthaltene Seite macht seinen Weg in die Ansicht . Beim Postback sind die enthaltenen Inhalte entgegen der Erwartung bereits in der rekonstruierten Ansicht vorhanden. Es ist also ein erwartetes Verhalten, dass Sie den genauen Teil der Ansicht gerendert haben.

Zur Lösung könnten Sie einfach eine erschöpfende Liste von statischen Includes einschließen, die in bedingt gerenderten <ui:fragment> JSF-Komponenten verpackt sind. Der Einfachheit halber könnte der gesamte Inhalt in einem Container wie <h:panelGroup> platziert werden, der immer zur Vereinfachung von AJAX-Aktualisierungen gerendert wird. Der Code könnte wie folgt zusammengesetzt werden:

<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> 
+0

Danke, aber in diesem Fall statisch enthalten sind keine Option.Die Komponenten sollten von Add-On-Frameworks aus angeschlossen werden, ohne die Hauptanwendung zu berühren. Wir hatten dort etwas fest programmiert, weshalb ich anfing, es durch eine dynamischere Lösung zu ersetzen. –

1

Ein klassisches Dilemma, so scheint es. BalusC's blog die Lösung für meinen Fall in Form eines Konfigurationsparameter in web.xml gab:

<context-param> 
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
    <param-value>false</param-value> 
</context-param>