Wofür können <f: metadata>, <f: viewParam> und <f: viewAction> verwendet werden?

149

Kann jemand klarstellen, wie wir dieses Snippet im Allgemeinen oder als Beispiel aus der Praxis verwenden können?

<f:metadata>
    <f:viewParam id="id" value="#{bean.id}" />
    <f:viewAction action="#{bean.init}" />
</f:metadata>
Hanynowsky
quelle

Antworten:

288

GET-Parameter verarbeiten

Das <f:viewParam>verwaltet die Einstellung, Konvertierung und Validierung von GET-Parametern. Es ist wie das <h:inputText>, aber dann für GET-Parameter.

Das folgende Beispiel

<f:metadata>
    <f:viewParam name="id" value="#{bean.id}" />
</f:metadata>

macht im Grunde das Folgende:

  • Ruft den Wert des Anforderungsparameters nach Namen ab id.
  • Konvertieren und validieren es notwendig , wenn (Sie verwenden können required, validatorund converterAttribute und Nest ein <f:converter>und <f:validator>in ihm wie wie mit <h:inputText>)
  • Wenn die Konvertierung und Validierung erfolgreich ist, legen Sie sie als Bean-Eigenschaft fest, die durch den #{bean.id}Wert dargestellt wird, oder wenn das valueAttribut fehlt, legen Sie sie als Anforderungsattribut für den Namen fest, iddamit sie #{id}in der Ansicht verfügbar ist .

Wenn Sie also die Seite so öffnen, wird der foo.xhtml?id=10Parameterwert auf 10diese Weise in der Bean festgelegt, unmittelbar bevor die Ansicht gerendert wird.

In Bezug auf die Validierung setzt der folgende Beispiel den Parameter auf required="true"und lässt nur Werte zwischen 10 und 20 zu. Jeder Validierungsfehler führt dazu, dass eine Meldung angezeigt wird.

<f:metadata>
    <f:viewParam id="id" name="id" value="#{bean.id}" required="true">
        <f:validateLongRange minimum="10" maximum="20" />
    </f:viewParam>
</f:metadata>
<h:message for="id" />

Ausführen von Geschäftsaktionen für GET-Parameter

Sie können das <f:viewAction>dafür verwenden.

<f:metadata>
    <f:viewParam id="id" name="id" value="#{bean.id}" required="true">
        <f:validateLongRange minimum="10" maximum="20" />
    </f:viewParam>
    <f:viewAction action="#{bean.onload}" />
</f:metadata>
<h:message for="id" />

mit

public void onload() {
    // ...
}

Das <f:viewAction>ist jedoch neu seit JSF 2.2 (das <f:viewParam>existiert bereits seit JSF 2.0). Wenn Sie kein Upgrade durchführen können, verwenden Sie <f:event>stattdessen am besten .

<f:event type="preRenderView" listener="#{bean.onload}" />

Dies wird jedoch bei jeder Anfrage aufgerufen . Sie müssen explizit prüfen, ob die Anfrage kein Postback ist:

public void onload() {
    if (!FacesContext.getCurrentInstance().isPostback()) {
        // ...
    }
}

Wenn Sie auch Fälle "Konvertierung / Validierung fehlgeschlagen" überspringen möchten, gehen Sie wie folgt vor:

public void onload() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if (!facesContext.isPostback() && !facesContext.isValidationFailed()) {
        // ...
    }
}

Die Verwendung <f:event>dieser Methode ist im Wesentlichen eine Problemumgehung / ein Hack. Genau deshalb <f:viewAction>wurde sie in JSF 2.2 eingeführt.


Übergeben Sie die Ansichtsparameter an die nächste Ansicht

Sie können die Ansichtsparameter in Navigationslinks "durchlaufen", indem Sie ein includeViewParamsAttribut festlegen trueoder einen includeViewParams=trueAnforderungsparameter hinzufügen .

<h:link outcome="next" includeViewParams="true">
<!-- Or -->
<h:link outcome="next?includeViewParams=true">

Das erzeugt mit dem obigen <f:metadata>Beispiel im Grunde den folgenden Link

<a href="next.xhtml?id=10">

mit dem ursprünglichen Parameterwert.

Dieser Ansatz erfordert nur , dass next.xhtmlsich auch ein <f:viewParam>auf demselben Parameter befindet, andernfalls wird er nicht durchlaufen.


Verwenden Sie GET-Formulare in JSF

Das <f:viewParam>kann auch in Kombination mit "einfachen HTML" GET-Formularen verwendet werden.

<f:metadata>
    <f:viewParam id="query" name="query" value="#{bean.query}" />
    <f:viewAction action="#{bean.search}" />
</f:metadata>
...
<form>
    <label for="query">Query</label>
    <input type="text" name="query" value="#{empty bean.query ? param.query : bean.query}" />
    <input type="submit" value="Search" />
    <h:message for="query" />
</form>
...
<h:dataTable value="#{bean.results}" var="result" rendered="#{not empty bean.results}">
     ...
</h:dataTable>

Mit im Grunde dieser @RequestScopedBohne:

private String query;
private List<Result> results;

public void search() {
    results = service.search(query);
}

Beachten Sie, dass das <h:message>für das <f:viewParam>, nicht das einfache HTML ist <input type="text">! Beachten Sie auch, dass der Eingabewert angezeigt wird, #{param.query}wenn er #{bean.query}leer ist, da der übermittelte Wert sonst bei einem Validierungs- oder Konvertierungsfehler überhaupt nicht angezeigt wird. Bitte beachten Sie, dass dieses Konstrukt für JSF-Eingabekomponenten ungültig ist (dies geschieht bereits "unter dem Deckmantel").


Siehe auch:

BalusC
quelle
@BalusC Was sollte der Umfang von "Bean" sein, wenn es in Verbindung mit Flaces-Redirect = True verwendet wird? Funktioniert es wie erwartet, wenn der Bereich auf "@RequestScoped" eingestellt ist?
Geek
@Geek: Eine Umleitung erstellt eine neue GET-Anforderung. Der Bean-Bereich der Quell- und Ziel-Bean ist irrelevant. Sie sollten jedoch die möglichen Auswirkungen einer neuen GET-Anforderung für eine Anforderung berücksichtigen und die Bean mit Gültigkeitsbereich anzeigen. Siehe auch stackoverflow.com/questions/7031885/…
BalusC
@BalusC Was genau meinen Sie mit "Sie sollten jedoch die möglichen Auswirkungen einer neuen GET-Anforderung für eine Anforderung berücksichtigen und die Bean mit Gültigkeitsbereich anzeigen."
Geek
@Geek: Sie werden verworfen und neu erstellt, da ihr Gültigkeitsbereich dann endet und beginnt.
BalusC
@ BalusC. Eine umfassende Antwort. "Wenn Sie eine '@' PostConstruct-ähnliche Funktion zum Anzeigen von Beans mit Gültigkeitsbereich verwenden müssen, die nicht bei jeder Anforderung aufgerufen wird, überprüfen Sie, ob die Anforderung kein Postback ist." Wenn es nicht bei jeder Anfrage aufgerufen wird, warum dann prüfen, ob es sich bei der Anfrage um ein Postback handelt oder nicht?
Uluk Biy