Do czego można użyć <f: metadata>, <f: viewParam> i <f: viewAction>?

149

Czy ktoś może wyjaśnić, w jaki sposób możemy ogólnie lub na przykładzie świata rzeczywistego użyć tego fragmentu?

<f:metadata>
    <f:viewParam id="id" value="#{bean.id}" />
    <f:viewAction action="#{bean.init}" />
</f:metadata>
Hanynowsky
źródło

Odpowiedzi:

288

Przetwarzaj parametry GET

<f:viewParam>Zarządza ustawień, konwersji i walidację parametrów GET. To jest jak <h:inputText>, ale potem dla parametrów GET.

Poniższy przykład

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

zasadniczo wykonuje następujące czynności:

  • Uzyskaj wartość parametru żądania według nazwy id.
  • Konwersja i zatwierdź ją, jeśli to konieczne (można użyć required, validatora converteratrybuty i zagnieździć <f:converter>i <f:validator>w nim jak jak z <h:inputText>)
  • Jeśli konwersja i walidacja zakończą się pomyślnie , ustaw go jako właściwość bean reprezentowaną przez #{bean.id}wartość lub jeśli valueatrybut jest nieobecny, ustaw go jako atrybut żądania w nazwie, idaby był dostępny #{id}w widoku.

Kiedy więc otworzysz stronę, foo.xhtml?id=10wtedy wartość parametru 10zostanie ustawiona w ziarnie w ten sposób, tuż przed renderowaniem widoku.

Jeśli chodzi o walidację, poniższy przykład ustawia parametr na required="true"i dopuszcza tylko wartości z przedziału od 10 do 20. Każde niepowodzenie walidacji spowoduje wyświetlenie komunikatu.

<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" />

Wykonywanie akcji biznesowej na parametrach GET

Możesz użyć <f:viewAction>do tego.

<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" />

z

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

Jest <f:viewAction>to jednak nowe od JSF 2.2 ( <f:viewParam>już istnieje od JSF 2.0). Jeśli nie możesz uaktualnić, najlepszym rozwiązaniem jest użycie <f:event>.

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

Jest to jednak przywoływane przy każdym żądaniu. Musisz wyraźnie sprawdzić, czy żądanie nie jest ogłoszeniem zwrotnym:

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

Jeśli chcesz również pominąć przypadki „Nieudana konwersja / walidacja”, wykonaj następujące czynności:

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

Używanie <f:event>tego sposobu jest w istocie obejściem / hackowaniem, właśnie dlatego <f:viewAction>został wprowadzony w JSF 2.2.


Przekaż parametry widoku do następnego widoku

Parametry widoku w linkach nawigacyjnych można „przekazywać”, ustawiając includeViewParamsatrybut truelub dodając includeViewParams=trueparametr żądania.

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

który generuje z powyższym <f:metadata>przykładem w zasadzie następujący link

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

z oryginalną wartością parametru.

Podejście to tylko wymaga , że next.xhtmlma również<f:viewParam> na tym samym parametrem, w przeciwnym razie nie będą przepuszczane.


Użyj formularzy GET w JSF

<f:viewParam>Może być również stosowany w połączeniu z „zwykły html” form GET.

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

Zasadniczo z tą @RequestScopedfasolą:

private String query;
private List<Result> results;

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

Zwróć uwagę, że <h:message>jest to plik <f:viewParam>, a nie zwykły kod HTML <input type="text">! Zwróć również uwagę, że wartość wejściowa jest wyświetlana, #{param.query}gdy #{bean.query}jest pusta, ponieważ przesłana wartość nie byłaby w ogóle wyświetlana w przypadku błędu weryfikacji lub konwersji. Zwróć uwagę, że ta konstrukcja jest nieprawidłowa dla komponentów wejściowych JSF (robi to już „pod osłonami”).


Zobacz też:

BalusC
źródło
@BalusC Jaki powinien być zakres wyrażenia „bean”, gdy jest używane w połączeniu z faces-redirect = true? Czy zadziała zgodnie z oczekiwaniami, jeśli zakres jest ustawiony na „@RequestScoped”?
Geek
@Geek: przekierowanie tworzy nowe żądanie GET. Zakres fasoli źródłowej i docelowej fasoli nie ma znaczenia. Należy jednak wziąć pod uwagę możliwe konsekwencje nowego żądania GET dla żądania i wyświetlić komponent bean z zakresem. Zobacz także stackoverflow.com/questions/7031885/…
BalusC
@BalusC Co dokładnie masz na myśli, mówiąc „Należy jednak wziąć pod uwagę możliwe konsekwencje nowego żądania GET dla żądania i wyświetlić komponent bean z zakresem”.
Geek
@Geek: Zostaną usunięte i odtworzone, ponieważ ich zakres zakończy się i rozpocznie.
BalusC
@BalusC. Kompleksowa odpowiedź. „Kiedy potrzebujesz użyć funkcji podobnej do PostConstruct '@' dla fasoli o zasięgu widoku, która nie jest wywoływana w każdym żądaniu, sprawdź, czy żądanie nie jest postbackiem”. Jeśli nie jest wywoływana przy każdym żądaniu, po co sprawdzać, czy żądanie jest zwrotem, czy nie?
Uluk Biy