Ändern JSF Komponentenbaum in Phaselistener
Frage
Ich bin ein Problem haben.
Ich habe eine Phaselistener implementiert, die einen Stil Klasse auf alle UIInput Komponenten in der Struktur, die Nachrichten mit ihnen verbunden haben hinzuzufügen, zu verstehen ist, und entfernt die Stilklasse, wenn es keine Nachrichten an sich hat.
Die Phaselistener laufen in der RENDER_RESPONSE Phase und funktioniert es sich beide in der beforePhase und afterPhase Methoden während des Debuggen. Während des Debuggens, fand ich, dass beforePhase keinen Zugriff auf die vollständigen Komponentenbaum hat, aber afterPhase tut. Alle Änderungen erfolgen in afterPhase werden nicht gerendert though.
Wie gehe ich dazu? Ich mag diese vollständig Server-Seite sein.
Danke,
James
Lösung 2
Implementiert einen Viewhandler verwenden, aber es ist nicht effizient. Phaselistener in Reaktionsphase Render keinen Zugriff auf Komponentenbaum hat.
Andere Tipps
Der JSF Komponentenbaum ist erst nach der Ansicht Bauzeit. Die RENDER_RESPONSE
Phase ist nicht unbedingt ein guter Zeitpunkt Zugriff auf den gesamten JSF Komponentenbaum haben, bevor sie gerendert wird. In einer ersten GET-Anforderung ohne <f:viewAction>
, ist der volle Komponentenbaum nur im afterPhase
zur Verfügung, wie es während der RENDER_RESPONSE
errichtet werden wird. Während eines Postbacks jedoch der volle Komponentenbaum in den beforePhase
verfügbar ist, wenn eine Navigation zu einer anderen Ansicht stattgefunden hat, dann wäre es geändert wird STIL während die RENDER_RESPONSE
Phase, so würden alle Änderungen verloren gehen .
Um zu erfahren, was genau die Ansicht Kompilierzeit ist, den Kopf auf die Frage Was die Ansicht Build Zeit ?
Sie wollen im Grunde eher auf „Ansicht Renderzeit“ hook als beforePhase
von RENDER_RESPONSE
Phase. JSF bietet mehr Möglichkeiten, darauf Haken:
-
In einiger Master-Vorlage, fügen Sie einen
preRenderView
Zuhörer<f:view>
.<f:view ...> <f:event type="preRenderView" listener="#{bean.onPreRenderView}" /> ... </f:view>
public void onPreRenderView(ComponentSystemEvent event) { UIViewRoot view = (UIViewRoot) event.getSource(); // The view is the component tree. Just modify it here accordingly. // ... }
-
Oder implementieren ein globales
SystemEventListener
fürPreRenderViewEvent
.public class YourPreRenderViewListener implements SystemEventListener { @Override public boolean isListenerForSource(Object source) { return source instanceof UIViewRoot; } @Override public void processEvent(SystemEvent event) throws AbortProcessingException { UIViewRoot view = (UIViewRoot) event.getSource(); // The view is the component tree. Just modify it here accordingly. // ... } }
Um es auszuführen, registrieren Sie es wie unten in
faces-config.xml
:<application> <system-event-listener> <system-event-listener-class>com.example.YourPreRenderViewListener</system-event-listener-class> <system-event-class>javax.faces.event.PreRenderViewEvent</system-event-class> </system-event-listener> </application>
-
Oder bieten eine benutzerdefinierte
ViewHandler
wobei Sie den Job inrenderView()
.public class YourViewHandler extends ViewHandlerWrapper { private ViewHandler wrapped; public YourViewHandler(ViewHandler wrapped) { this.wrapped = wrapped; } @Override public void renderView(FacesContext context, UIViewRoot view) { // The view is the component tree. Just modify it here accordingly. // ... // Finally call super so JSF can do the rendering job. super.renderView(context, view); } @Override public ViewHandler getWrapped() { return wrapped; } }
Um es auszuführen, registrieren, wie unten in
faces-config.xml
:<application> <view-handler>com.example.YourViewHandler</view-handler> </application>
-
Oder Haken auf OmniFaces hat eine
<o:highlight>
Komponente, die dies tut genau das.