Busque en la salida HTML la identificación real del cliente
Debe buscar en la salida HTML generada para encontrar la ID de cliente correcta. Abra la página en el navegador, haga clic derecho y Ver código fuente . Localice la representación HTML del componente JSF de interés y tómelo id
como ID de cliente. Puede usarlo de manera absoluta o relativa, dependiendo del contenedor de nombres actual. Ver el siguiente capítulo.
Nota: si pasa a contener iteración índice como :0:
, :1:
, etc (porque es un componente dentro de la iteración), entonces usted necesita para darse cuenta de que la actualización de una ronda específica iteración no siempre es compatible. Vea la parte inferior de la respuesta para obtener más detalles al respecto.
Memorice NamingContainer
componentes y siempre déles una identificación fija
Si un componente al que le gustaría hacer referencia mediante el proceso / ejecución / actualización / renderización de ajax está dentro del mismo NamingContainer
padre, simplemente haga referencia a su propia ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Si se trata de no dentro de la misma NamingContainer
, entonces es necesario hacer referencia a ella mediante un ID de cliente absoluta. Un ID de cliente absoluto comienza con el NamingContainer
carácter separador, que es el predeterminado :
.
<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
componentes son, por ejemplo <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(por lo tanto, todos los componentes de material compuesto), etc. Se les reconocen fácilmente mirando en la salida HTML generado, su identificación se antepondrá a la ID de cliente generado de todos los componentes hijos. Tenga en cuenta que cuando no tienen una ID fija, JSF usará una ID autogenerada en j_idXXX
formato. Debería evitarlo absolutamente dándoles una identificación fija. Los OmniFacesNoAutoGeneratedIdViewHandler
pueden ser útiles en este durante el desarrollo.
Si sabe encontrar el javadoc de la UIComponent
pregunta en cuestión, también puede verificar si implementa la NamingContainer
interfaz o no. Por ejemplo, HtmlForm
(la etiqueta UIComponent
detrás <h:form>
) muestra que se implementa NamingContainer
, pero HtmlPanelGroup
(la etiqueta UIComponent
detrás <h:panelGroup>
) no lo muestra, por lo que no se implementa NamingContainer
. Aquí está el javadoc de todos los componentes estándar y aquí está el javadoc de PrimeFaces .
Resolviendo tu problema
Entonces en tu caso de:
<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">
El resultado HTML generado de se <h:panelGrid id="display">
ve así:
<table id="tabs:insTable:display">
Debe tomar exactamente eso id
como ID de cliente y luego prefijar con :
para su uso en update
:
<p:commandLink update=":tabs:insTable:display">
Referencias externas incluyen / tagfile / composite
Si este enlace de comando está dentro de un archivo de inclusión / etiqueta, y el destino está fuera de él, y por lo tanto no necesariamente conoce la ID del contenedor de nombres principal del contenedor de nombres actual, puede hacer referencia dinámica de esta UIComponent#getNamingContainer()
manera:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
O, si este enlace de comando está dentro de un componente compuesto y el objetivo está fuera de él:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
O, si tanto el enlace de comando como el objetivo están dentro del mismo componente compuesto:
<p:commandLink update=":#{cc.clientId}:display">
Consulte también Obtener ID del contenedor de nombres principal en la plantilla para el atributo de render / actualización
¿Cómo funciona debajo de las sábanas?
Todo esto se especifica como "expresión de búsqueda" en el UIComponent#findComponent()
javadoc :
Una expresión de búsqueda consiste en un identificador (que coincide exactamente con la propiedad id de a UIComponent
, o una serie de identificadores vinculados por el UINamingContainer#getSeparatorChar
valor del carácter. El algoritmo de búsqueda debe funcionar de la siguiente manera, aunque se pueden usar algoritmos alternativos siempre que El resultado final es el mismo:
- Identifique lo
UIComponent
que será la base para la búsqueda, deteniéndose tan pronto como se cumpla una de las siguientes condiciones:
- Si la expresión de búsqueda comienza con el carácter separador (llamado expresión de búsqueda "absoluta"), la base será la raíz
UIComponent
del árbol de componentes. El carácter separador inicial se eliminará y el resto de la expresión de búsqueda se tratará como una expresión de búsqueda "relativa" como se describe a continuación.
- De lo contrario, si esto
UIComponent
es un NamingContainer
servirá de base.
- De lo contrario, busque los padres de este componente. Si
NamingContainer
se encuentra un, será la base.
- De lo contrario (si no
NamingContainer
se encuentra), la raíz UIComponent
será la base.
- La expresión de búsqueda (posiblemente modificada en el paso anterior) ahora es una expresión de búsqueda "relativa" que se usará para ubicar el componente (si lo hay) que tiene una identificación que coincide, dentro del alcance del componente base. El partido se realiza de la siguiente manera:
- Si la expresión de búsqueda es un identificador simple, este valor se compara con la propiedad id, y luego recursivamente a través de las facetas y los elementos secundarios de la base
UIComponent
(excepto que si NamingContainer
se encuentra un descendiente , no se buscan sus propias facetas y elementos secundarios).
- Si la expresión de búsqueda incluye más de un identificador separado por el carácter separador, el primer identificador se utiliza para ubicar a
NamingContainer
por las reglas en el punto anterior. Luego, se llamará al findComponent()
método de esta NamingContainer
, pasando el resto de la expresión de búsqueda.
Tenga en cuenta que PrimeFaces también cumple con la especificación JSF, pero RichFaces usa "algunas excepciones adicionales" .
"reRender" usa un UIComponent.findComponent()
algoritmo (con algunas excepciones adicionales) para encontrar el componente en el árbol de componentes.
Esas excepciones adicionales no se describen en detalle en ninguna parte, pero se sabe que los ID de componentes relativos (es decir, aquellos que no comienzan con :
) no solo se buscan en el contexto del padre más cercano NamingContainer
, sino también en todos los demás NamingContainer
componentes en la misma vista (que es relativamente trabajo costoso por cierto).
Nunca usar prependId="false"
Si todo esto aún no funciona, verifique si no lo está utilizando <h:form prependId="false">
. Esto fallará durante el procesamiento del envío y el procesamiento de ajax. Consulte también esta pregunta relacionada: UIForm with prependId = "false" rompe <f: ajax render> .
Hacer referencia a ronda de iteración específica de componentes iterativos
Durante mucho tiempo no fue posible hacer referencia a un elemento iterado específico en componentes iterativos como <ui:repeat>
y <h:dataTable>
así:
<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>
Sin embargo, desde Mojarra 2.2.5 <f:ajax>
comenzó a admitirlo (simplemente dejó de validarlo; por lo tanto, nunca más se enfrentaría a la excepción mencionada en la pregunta; se planea otra solución de mejora para eso más adelante).
Esto solo no funciona aún en las versiones actuales de MyFaces 2.2.7 y PrimeFaces 5.2. El soporte podría venir en futuras versiones. Mientras tanto, su mejor opción es actualizar el componente iterativo en sí, o un padre en caso de que no represente HTML, como <ui:repeat>
.
Cuando use PrimeFaces, considere Expresiones de búsqueda o Selectores
PrimeFaces Search Expressions le permite hacer referencia a componentes a través de expresiones de búsqueda de árbol de componentes JSF. JSF tiene varios incorporados:
@this
: componente actual
@form
: padre UIForm
@all
: documento completo
@none
: nada
PrimeFaces ha mejorado esto con nuevas palabras clave y compatibilidad con expresiones compuestas:
@parent
: componente principal
@namingcontainer
: padre UINamingContainer
@widgetVar(name)
: componente identificado por dado widgetVar
También se pueden mezclar las palabras clave en expresiones compuestas, tales como @form:@parent
, @this:@parent:@parent
, etc.
PrimeFaces Selectors (PFS) como en le @(.someclass)
permite hacer referencia a componentes a través de la sintaxis del selector CSS jQuery. Por ejemplo, hacer referencia a componentes que tienen toda una clase de estilo común en la salida HTML. Esto es particularmente útil en caso de que necesite hacer referencia a "muchos" componentes. Esto solo requiere que los componentes de destino tengan una ID de cliente en la salida HTML (fija o autogenerada, no importa). Consulte también ¿Cómo funcionan los selectores PrimeFaces como en update = "@ (. MyClass)"?