Cerca nell'output HTML l'ID client effettivo
Devi cercare nell'output HTML generato per scoprire l'ID client corretto. Apri la pagina nel browser, fai clic con il pulsante destro del mouse e Visualizza sorgente . Individua la rappresentazione HTML del componente JSF di interesse e prendila id
come ID client. Puoi usarlo in modo assoluto o relativo a seconda dell'attuale contenitore dei nomi. Vedi il capitolo seguente.
Nota: se capita di contenere un indice di iterazione come :0:
, :1:
ecc. (Perché si trova all'interno di un componente iterante), è necessario rendersi conto che l'aggiornamento di un ciclo di iterazione specifico non è sempre supportato. Vedi fondo della risposta per maggiori dettagli al riguardo.
Memorizza i NamingContainer
componenti e assegna loro sempre un ID fisso
Se un componente a cui desideri fare riferimento tramite ajax process / execute / update / render è all'interno dello stesso NamingContainer
genitore, fai semplicemente riferimento al suo ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Se non si trova all'interno dello stesso NamingContainer
, è necessario fare riferimento a esso utilizzando un ID client assoluto. Un ID client assoluto inizia con il NamingContainer
carattere separatore, che è per impostazione predefinita :
.
<h:form id="form">
<p:commandLink update="result"> <!-- FAIL! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- FAIL! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
<h:form id="form">
<p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
NamingContainer
componenti sono per esempio <h:form>
,<h:dataTable>
, <p:tabView>
, <cc:implementation>
(in tal modo, tutti i componenti in composito), ecc Li riconoscono facilmente osservando l'output HTML generato, il loro ID verrà anteposto al ID client generato di tutti i componenti figlio. Quando non hanno un ID fisso, JSF utilizzerà un ID generato automaticamente nel j_idXXX
formato. Dovresti assolutamente evitarlo dando loro un ID fisso. I OmniFacesNoAutoGeneratedIdViewHandler
possono essere utili in questa fase di sviluppo.
Se sai di trovare il javadoc UIComponent
in questione, puoi anche controllare lì se implementa l' NamingContainer
interfaccia o meno. Ad esempio, il HtmlForm
(il tag UIComponent
dietro <h:form>
) mostra che implementa NamingContainer
, ma il HtmlPanelGroup
(il UIComponent
dietro<h:panelGroup>
tag ) non lo mostra, quindi non lo implementa NamingContainer
. Ecco il javadoc di tutti i componenti standard ed ecco il javadoc di PrimeFaces .
Risolvere il tuo problema
Quindi nel tuo caso di:
<p:tabView id="tabs"><!-- This is a NamingContainer -->
<p:tab id="search"><!-- This is NOT a NamingContainer -->
<h:form id="insTable"><!-- This is a NamingContainer -->
<p:dialog id="dlg"><!-- This is NOT a NamingContainer -->
<h:panelGrid id="display">
L'output HTML generato di <h:panelGrid id="display">
è simile al seguente:
<table id="tabs:insTable:display">
Devi prenderlo esattamente id
come ID client e quindi aggiungere il prefisso :
per l'utilizzo inupdate
:
<p:commandLink update=":tabs:insTable:display">
I riferimenti all'esterno includono / tagfile / composite
Se questo collegamento di comando si trova all'interno di un file include / tag e la destinazione si trova all'esterno di esso, pertanto non si conosce necessariamente l'ID del contenitore contenitore di denominazione del contenitore di denominazione corrente, quindi è possibile fare riferimento dinamicamente tramite UIComponent#getNamingContainer()
così:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Oppure, se questo collegamento di comando si trova all'interno di un componente composito e la destinazione si trova all'esterno di esso:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Oppure, se sia il comando link che la destinazione sono all'interno dello stesso componente composito:
<p:commandLink update=":#{cc.clientId}:display">
Guarda anche Ottieni ID del contenitore di denominazione principale nel modello per l'attributo in rendering / update
Come funziona sotto le coperte
Tutto questo è specificato come "ricerca espressione" nella UIComponent#findComponent()
javadoc :
Un'espressione di ricerca è costituito da un identificatore (che corrisponde esattamente contro la proprietà id di una UIComponent
, o una serie di tali identificatori collegate dal UINamingContainer#getSeparatorChar
valore di carattere. L'algoritmo ricerca deve opera come segue, se alogrithms alternativi possono essere utilizzati purché la il risultato finale è lo stesso:
- Identifica quella
UIComponent
che sarà la base per la ricerca, fermandoti non appena viene soddisfatta una delle seguenti condizioni:
- Se l'espressione di ricerca inizia con il carattere separatore (chiamato espressione di ricerca "assoluta"), la base sarà la radice
UIComponent
dell'albero dei componenti. Il carattere separatore principale verrà rimosso e il resto dell'espressione di ricerca verrà trattato come un'espressione di ricerca "relativa" come descritto di seguito.
- Altrimenti, se questo
UIComponent
è un NamingContainer
, servirà come base.
- Altrimenti, cerca i genitori di questo componente. Se
NamingContainer
si incontra a, sarà la base.
- Altrimenti (se non
NamingContainer
si incontra) la radice UIComponent
sarà la base.
- L'espressione di ricerca (eventualmente modificata nel passaggio precedente) è ora un'espressione di ricerca "relativa" che verrà utilizzata per individuare il componente (se presente) che ha un ID corrispondente, nell'ambito del componente di base. La partita si svolge come segue:
- Se l'espressione di ricerca è un identificatore semplice, questo valore viene confrontato con la proprietà id, quindi ricorsivamente attraverso le sfaccettature e i figli della base
UIComponent
(tranne che se NamingContainer
viene trovato un discendente , le sue sfaccettature e i suoi figli non vengono cercati).
- Se l'espressione di ricerca include più di un identificatore separato dal carattere separatore, il primo identificatore viene utilizzato per individuare a
NamingContainer
secondo le regole nel punto elenco precedente. Quindi, verrà chiamato il findComponent()
metodo di questo NamingContainer
, passando il resto dell'espressione di ricerca.
Si noti che anche PrimeFaces aderisce alle specifiche JSF, ma RichFaces utilizza "alcune eccezioni aggiuntive" .
"reRender" utilizza l' UIComponent.findComponent()
algoritmo (con alcune eccezioni aggiuntive) per trovare il componente nella struttura dei componenti.
Queste ulteriori eccezioni non sono descritte in alcun dettaglio, ma è noto che gli ID dei componenti relativi (ovvero quelli che non iniziano con :
) non vengono cercati solo nel contesto del genitore più vicino NamingContainer
, ma anche in tutti gli altri NamingContainer
componenti nella stessa vista (che è relativamente lavoro costoso a proposito).
Non usare mai prependId="false"
Se tutto continua a non funzionare, verifica se non lo stai utilizzando <h:form prependId="false">
. Ciò fallirà durante l'elaborazione dell'invio e del rendering di Ajax. Vedi anche questa domanda correlata: UIForm con prependId = "false" si rompe <f: ajax render> .
Facendo riferimento al ciclo di iterazione specifico dei componenti iteranti
Per molto tempo non è stato possibile fare riferimento a un elemento iterato specifico in componenti iteranti simili <ui:repeat>
e <h:dataTable>
simili:
<h:form id="form">
<ui:repeat id="list" value="#{['one','two','three']}" var="item">
<h:outputText id="item" value="#{item}" /><br/>
</ui:repeat>
<h:commandButton value="Update second item">
<f:ajax render=":form:list:1:item" />
</h:commandButton>
</h:form>
Tuttavia, dal momento che Mojarra 2.2.5 ha <f:ajax>
iniziato a supportarlo (ha semplicemente smesso di convalidarlo; quindi non dovresti mai più affrontare l'eccezione nella domanda menzionata; un'altra correzione del miglioramento è prevista in seguito).
Questo non funziona ancora nelle attuali versioni di MyFaces 2.2.7 e PrimeFaces 5.2. Il supporto potrebbe venire nelle versioni future. Nel frattempo, la soluzione migliore è aggiornare il componente iterante stesso o un genitore nel caso in cui non esegua il rendering HTML, come <ui:repeat>
.
Quando si utilizzano PrimeFaces, considerare le espressioni di ricerca o i selettori
PrimeFaces Search Expressions consente di fare riferimento ai componenti tramite le espressioni di ricerca dell'albero dei componenti JSF. JSF ha diversi builtin:
@this
: componente corrente
@form
: genitore UIForm
@all
: intero documento
@none
: Niente
PrimeFaces ha migliorato questo aspetto con nuove parole chiave e supporto per espressioni composite:
@parent
: componente principale
@namingcontainer
: genitore UINamingContainer
@widgetVar(name)
: componente identificato da dato widgetVar
È inoltre possibile combinare tali parole chiave nelle espressioni compositi come @form:@parent
, @this:@parent:@parent
, etc.
PrimeFaces Selectors (PFS) come in @(.someclass)
consente di fare riferimento ai componenti tramite la sintassi del selettore CSS jQuery. Ad esempio, i componenti di riferimento che hanno una classe di stile comune nell'output HTML. Ciò è particolarmente utile nel caso in cui sia necessario fare riferimento a "molti" componenti. Ciò presuppone solo che i componenti di destinazione abbiano tutti un ID client nell'output HTML (fisso o generato automaticamente, non importa). Vedi anche Come funzionano i selettori PrimeFaces come in update = "@ (. MyClass)"?