Apa yang bisa digunakan <f: metadata>, <f: viewParam> dan <f: viewAction>?

149

Adakah yang bisa menjelaskan bagaimana kita dapat menggunakan cuplikan ini secara umum, atau di dunia nyata?

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

Jawaban:

288

Memproses parameter GET

The <f:viewParam>mengelola pengaturan, konversi dan validasi parameter GET. Ini seperti <h:inputText>, tetapi kemudian untuk parameter GET.

Contoh berikut

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

pada dasarnya melakukan hal berikut:

  • Dapatkan nilai parameter permintaan berdasarkan nama id.
  • Konversikan dan validasikan jika perlu (Anda dapat menggunakan required, validatordan converteratribut dan sarang a <f:converter>dan <f:validator>di dalamnya seperti dengan <h:inputText>)
  • Jika konversi dan validasi berhasil, maka tetapkan sebagai properti bean yang diwakili oleh #{bean.id}nilai, atau jika valueatribut tidak ada, maka tetapkan sebagai permintaan, tertera nama idsehingga tersedia #{id}dalam tampilan.

Jadi ketika Anda membuka halaman foo.xhtml?id=10saat nilai parameter 10diatur dalam kacang dengan cara ini, tepat sebelum tampilan diberikan.

Mengenai validasi, contoh berikut ini mengatur param ke required="true"dan memungkinkan hanya nilai antara 10 dan 20. Setiap kegagalan validasi akan menghasilkan pesan yang ditampilkan.

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

Melakukan tindakan bisnis pada parameter GET

Anda dapat menggunakan <f:viewAction>ini untuk ini.

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

dengan

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

The <f:viewAction>namun baru sejak JSF 2.2 (yang <f:viewParam>sudah ada sejak JSF 2.0). Jika Anda tidak dapat meningkatkan, maka taruhan terbaik Anda adalah menggunakan <f:event>.

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

Namun ini diminta pada setiap permintaan. Anda perlu memeriksa secara eksplisit apakah permintaan tersebut bukan postback:

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

Saat Anda ingin melewatkan kasus "Konversi / Validasi gagal" juga, lakukan sebagai berikut:

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

Menggunakan <f:event>cara ini pada dasarnya adalah solusi / peretasan, itulah sebabnya <f:viewAction>diperkenalkan di JSF 2.2.


Lewati parameter tampilan ke tampilan berikutnya

Anda dapat "melewati" parameter tampilan di tautan navigasi dengan menyetel includeViewParamsatribut ke trueatau dengan menambahkan includeViewParams=trueparameter permintaan.

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

yang menghasilkan dengan <f:metadata>contoh di atas pada dasarnya tautan berikut

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

dengan nilai parameter asli.

Pendekatan ini hanya membutuhkan bahwa next.xhtmlmemiliki juga sebuah <f:viewParam>pada parameter yang sama, jika tidak maka tidak akan melewati.


Gunakan formulir GET di JSF

The <f:viewParam>juga dapat digunakan dalam kombinasi dengan "plain HTML" bentuk 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>

Pada dasarnya @RequestScopedkacang ini :

private String query;
private List<Result> results;

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

Perhatikan bahwa <h:message>ini untuk <f:viewParam>, bukan HTML biasa <input type="text">! Perhatikan juga bahwa nilai input ditampilkan #{param.query}ketika #{bean.query}kosong, karena nilai yang dikirimkan tidak akan muncul sama sekali ketika ada kesalahan validasi atau konversi. Harap dicatat bahwa konstruk ini tidak valid untuk komponen input JSF (sudah melakukan itu "di bawah penutup").


Lihat juga:

BalusC
sumber
@ BalusC Apa yang seharusnya menjadi ruang lingkup "bean" bila digunakan bersama dengan wajah-redirect = true? Apakah ini akan berfungsi seperti yang diharapkan jika cakupan diatur ke "@RequestScoped"?
Geek
@Geek: Pengalihan membuat permintaan GET baru. Lingkup kacang sumber dan kacang target tidak relevan. Namun Anda harus mempertimbangkan kemungkinan implikasi dari permintaan GET baru untuk permintaan dan melihat kacang scoped. Lihat juga stackoverflow.com/questions/7031885/…
BalusC
@BalusC Apa yang sebenarnya Anda maksud dengan "Namun Anda harus mempertimbangkan implikasi yang mungkin dari permintaan GET baru untuk permintaan dan melihat kacang yang dicakup."
Geek
@ Geek: Mereka akan dibuang dan diciptakan kembali karena ruang lingkup mereka kemudian akan berakhir dan mulai.
BalusC
@BalusC. Jawaban yang komprehensif. "Ketika Anda perlu menggunakan fitur '@' PostConstruct like untuk melihat kacang scoped yang tidak dipanggil pada setiap permintaan, periksa apakah permintaan tersebut bukan postback". Jika tidak diminta pada setiap permintaan, lalu mengapa memeriksa apakah permintaan tersebut adalah postback atau tidak?
Uluk Biy