JSTL in Facelets JSF2 ha senso?

Vorrei produrre un po ‘di codice Facelets in modo condizionale.

A tale scopo, i tag JSTL sembrano funzionare correttamente:

 ...  

Tuttavia, non sono sicuro che sia una best practice? C’è un altro modo per raggiungere il mio objective?

introduzione

I JSTL sono tutti taghandler e vengono eseguiti durante il tempo di generazione delle viste , mentre i JSF sono tutti componenti dell’interfaccia utente e vengono eseguiti durante il tempo di rendering della vista .

Nota che dai e JSF solo quelli che non si estendono da UIComponent sono anche taghandler, ad esempio , , , ecc. Quelli che si estendono da UIComponent sono anche componenti dell’interfaccia utente JSF, ad esempio , , , ecc. Dalle componenti dell’interfaccia utente JSF vengono valutati solo gli attributi id e binding durante il tempo di creazione della vista . Pertanto la risposta di seguito relativa al ciclo di vita JSTL si applica anche agli attributi id e binding dei componenti JSF.

Il tempo di generazione della vista è il momento in cui il file XHTML / JSP deve essere analizzato e convertito in una struttura di componenti JSF che viene quindi memorizzata come UIViewRoot di FacesContext . Il tempo di rendering della vista è quel momento in cui l’albero dei componenti JSF sta per generare HTML, a partire da UIViewRoot#encodeAll() . Quindi: i componenti dell’interfaccia utente JSF e i tag JSTL non vengono eseguiti in sincronizzazione come ci si aspetterebbe dalla codifica. Puoi visualizzarlo come segue: JSTL viene eseguito dapprima dall’alto verso il basso, producendo l’albero dei componenti JSF, quindi è il turno di JSF di eseguire di nuovo dall’alto verso il basso, producendo l’output HTML.

vs

Ad esempio, questo marcatore Facelets che itera su 3 elementi usando :

    

… crea durante la visualizzazione del tempo di compilazione tre componenti separati nell’albero del componente JSF, rappresentati in modo approssimativo come questo:

    

… che a loro volta generano individualmente il loro output HTML durante il tempo di rendering della vista:

 value1 value2 value3 

Si noti che è necessario garantire manualmente l’univocità degli ID dei componenti e che questi vengono anche valutati durante il tempo di creazione delle viste.

Mentre questo marcatore Facelets itera su 3 elementi usando , che è un componente dell’interfaccia utente JSF:

    

… già finisce così com’è nell’albero del componente JSF per cui lo stesso componente è durante il tempo di rendering della vista che viene riutilizzato per generare l’output HTML in base al round di iterazione corrente:

 value1 value2 value3 

Si noti che il come componente NamingContainer già assicurato l’unicità dell’ID client in base all’indice di iterazione; non è inoltre ansible utilizzare EL nell’attributo id dei componenti figlio in questo modo poiché viene anche valutato durante la fase di creazione della vista mentre #{item} è disponibile solo durante il tempo di rendering della vista. Lo stesso vale per h:dataTable e componenti simili.

/ vs rendered

Come altro esempio, questa marcatura Facelets aggiunge in modo condizionale tag diversi usando (puoi usare anche per questo):

          

… in caso di type = TEXT aggiunge solo il componente componente JSF:

  

Mentre questo markup Facelets:

    

… finirà esattamente come sopra nell’albero del componente JSF indipendentemente dalle condizioni. Questo può quindi finire in un albero di componenti “gonfio” quando ne hai molti e in realtà sono basati su un modello “statico” (cioè il field non cambia mai durante almeno l’ambito della vista). Inoltre, potresti incontrare problemi EL quando gestisci sottoclassi con proprietà aggiuntive nelle versioni di Mojarra precedenti alla 2.2.7.

vs

Non sono intercambiabili. imposta una variabile nello scope EL, che è accessibile solo dopo la posizione della tag durante il tempo di creazione della vista, ma in qualsiasi punto della vista durante il tempo di rendering della vista. passa una variabile EL a un modello di Facelet incluso tramite , decor o . Le versioni precedenti di JSF avevano bug per cui la variabile è anche disponibile al di fuori del modello Facelet in questione, questo non dovrebbe mai essere invocato.

senza un attributo scope si comporterà come un alias. Non memorizza nella cache il risultato dell’espressione EL in qualsiasi ambito. Può quindi essere usato perfettamente all’interno, ad esempio, per iterare i componenti JSF. Quindi, per esempio sotto funzionerà bene:

     

Non è adatto ad esempio per calcolare la sum in un ciclo. Per questo invece usa lo stream EL 3.0 :

  ...  

Total price: #{bean.products.stream().map(product->product.price).sum()}

Solo, quando si imposta l’attributo scope con una request valori ammissibili, view , session o application , questa verrà valutata immediatamente durante la fase di creazione della vista e archiviata nell’ambito specificato.

  

Questo verrà valutato solo una volta e disponibile come #{dev} nell’intera applicazione.

Utilizzare JSTL per controllare la struttura ad albero dei componenti JSF

L’utilizzo di JSTL può portare a risultati imprevisti solo quando vengono utilizzati all’interno di componenti JSF come , , ecc, o quando gli attributi dei tag JSTL dipendono dai risultati di eventi JSF come preRenderView o valori di modulo inoltrati in il modello che non è disponibile durante il tempo di creazione della vista. Quindi, utilizzare i tag JSTL solo per controllare il stream della struttura ad albero dei componenti JSF. Utilizzare i componenti dell’interfaccia utente JSF per controllare il stream della generazione di output HTML. Non associare la var di iterazione dei componenti JSF agli attributi del tag JSTL. Non fare affidamento sugli eventi JSF negli attributi dei tag JSTL.

Ogni volta che pensi di dover associare un componente al backing bean tramite binding , o findComponent() uno tramite findComponent() , e creare / manipolare i suoi figli usando il codice Java in un backing bean con new SomeComponent() e cosa no, allora dovresti immediatamente fermati e considera l’utilizzo di JSTL. Poiché JSTL è anche basato su XML, il codice necessario per creare dynamicmente componenti JSF diventerà molto più leggibile e manutenibile.

È importante sapere che le versioni di Mojarra precedenti alla 2.1.18 avevano un bug nel salvataggio parziale dello stato quando si fa riferimento a un bean con scope vista in un attributo tag JSTL. L’intero bean con ambito di visualizzazione verrebbe ricreato nuovamente anziché recuperato dall’albero delle viste (semplicemente perché l’albero di visualizzazione completo non è ancora disponibile al punto in cui viene eseguito JSTL). Se stai aspettando o memorizzando alcuni stati nel bean con scope vista da un attributo tag JSTL, allora non restituirà il valore che ti aspetti, o sarà “perso” nel bean con scope vista reale che viene ripristinato dopo la vista l’albero è costruito Nel caso in cui non sia ansible eseguire l’aggiornamento a Mojarra 2.1.18 o successivi, è necessario distriggersre il salvataggio parziale di stato in web.xml come di seguito:

  javax.faces.PARTIAL_STATE_SAVING false  

Guarda anche:

  • Qual è il tempo di costruzione della visualizzazione?
  • Come funziona l’attributo ‘binding’ in JSF? Quando e come dovrebbe essere usato?
  • Come refettare lo snippet del vecchio JSP con un equivalente JSF?
  • PARTIAL_STATE_SAVING dovrebbe essere impostato su false?
  • Comunicazione in JSF 2.0 – @ViewScoped esito negativo nei gestori di tag

Per vedere alcuni esempi del mondo reale in cui i tag JSTL sono utili (ad esempio quando vengono utilizzati correttamente durante la creazione della vista), vedere le seguenti domande / risposte:

  • Come creare una griglia di componenti compositi JSF?
  • Crea colonne di tabelle dynamicmente in JSF
  • Come layout personalizzato h: selectOneRadio
  • Definizione della variabile condizionale in JSF
  • Come rendere il componente composito simile a
  • JSF 2 – Componente composito con attributo listener facoltativo su f: ajax
  • Nested JSF Composite Components che portano a un’eccezione di overflow dello stack

In poche parole

Per quanto riguarda i requisiti funzionali concreti, se si desidera rendere condizionatamente i componenti JSF, utilizzare invece l’attributo rendered sul componente HTML JSF, in particolare se #{lpc} rappresenta l’elemento attualmente iterato di un componente JSF come o .

  ...  

Oppure, se si desidera creare (creare / aggiungere) componenti JSF in modo condizionale, continuare a utilizzare JSTL. È molto meglio che eseguire new SomeComponent() in java.

   ...   

Guarda anche:

  • Visualizzazione condizionale dei componenti JSF
  • JSTL c: se non funziona all’interno di una JSF h: dataTable
  • Specifica il rendering condizionale dell’elemento all’interno di ? non sembra funzionare

uso

  ...  

Ci scusiamo per la risposta separata, ma non ho potuto commentare le risposte sopra.

Per l’output di tipo switch, è ansible utilizzare switch da primefaces-extensions .