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 idcome 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 NamingContainercomponenti 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 NamingContainergenitore, 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 NamingContainercarattere 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>
NamingContainercomponenti 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_idXXXformato. Dovresti assolutamente evitarlo dando loro un ID fisso. I OmniFacesNoAutoGeneratedIdViewHandler possono essere utili in questa fase di sviluppo.
Se sai di trovare il javadoc UIComponentin questione, puoi anche controllare lì se implementa l' NamingContainerinterfaccia o meno. Ad esempio, il HtmlForm(il tag UIComponentdietro <h:form>) mostra che implementa NamingContainer, ma il HtmlPanelGroup(il UIComponentdietro<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 idcome 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#getSeparatorCharvalore di carattere. L'algoritmo ricerca deve opera come segue, se alogrithms alternativi possono essere utilizzati purché la il risultato finale è lo stesso:
- Identifica quella
UIComponentche 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
UIComponentdell'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
NamingContainersi incontra a, sarà la base.
- Altrimenti (se non
NamingContainersi incontra) la radice UIComponentsarà 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 NamingContainerviene 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
NamingContainersecondo 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 NamingContainercomponenti 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)"?