Procure na saída HTML o ID do cliente real
Você precisa procurar na saída HTML gerada para descobrir o ID do cliente correto. Abra a página no navegador, clique com o botão direito e em Exibir fonte . Localize a representação HTML do componente JSF de interesse e use-o id
como ID do cliente. Você pode usá-lo de maneira absoluta ou relativa, dependendo do contêiner de nomenclatura atual. Veja o capítulo seguinte.
Nota: se tiver um índice de iteração como :0:
, :1:
etc (porque está dentro de um componente de iteração), será necessário perceber que a atualização de uma rodada de iteração específica nem sempre é suportada. Veja a parte inferior da resposta para mais detalhes.
Memorize NamingContainer
componentes e sempre dê a eles um ID fixo
Se um componente que você gostaria de referenciar por ajax process / execute / update / render estiver dentro do mesmo NamingContainer
pai, basta fazer referência ao seu próprio ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Se é não dentro da mesma NamingContainer
, então você precisa fazer referência a ela usando um ID do cliente absoluta. Um ID de cliente absoluto começa com o NamingContainer
caractere separador, que é por padrão :
.
<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 são, por exemplo <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(assim, todos os componentes em materiais compósitos), etc. Você reconhecê-los facilmente, olhando para a saída HTML gerado, seu ID será anexado ao ID do cliente gerado de todos os componentes filhos. Observe que quando eles não têm um ID fixo, o JSF usará um ID gerado automaticamente no j_idXXX
formato. Você deve absolutamente evitar isso, dando a eles um ID fixo. O OmniFacesNoAutoGeneratedIdViewHandler
pode ser útil nisso durante o desenvolvimento.
Se você souber encontrar o javadoc do UIComponent
em questão, também poderá verificar se ele implementa a NamingContainer
interface ou não. Por exemplo, a HtmlForm
(a marca de UIComponent
trás <h:form>
) mostra que ela é implementada NamingContainer
, mas a HtmlPanelGroup
(a marca de UIComponent
trás <h:panelGroup>
) não a mostra e, portanto, não é implementada NamingContainer
. Aqui está o javadoc de todos os componentes padrão e o javadoc do PrimeFaces .
Resolvendo seu problema
Então, no seu 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">
A saída HTML gerada se <h:panelGrid id="display">
parece com isso:
<table id="tabs:insTable:display">
Você precisa usar exatamente isso id
como ID do cliente e prefixar com o :
uso em update
:
<p:commandLink update=":tabs:insTable:display">
Referenciar fora include / tagfile / composite
Se esse link de comando estiver dentro de um include / tagfile e o destino estiver fora dele, você não conhecerá necessariamente o ID do pai do contêiner de nomeação do contêiner de nomeação atual, poderá fazer referência dinâmica a ele da seguinte UIComponent#getNamingContainer()
maneira:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Ou, se este link de comando estiver dentro de um componente composto e o destino estiver fora dele:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Ou, se o link de comando e o destino estiverem dentro do mesmo componente composto:
<p:commandLink update=":#{cc.clientId}:display">
Consulte também Obter identificação do contêiner de nomeação pai no modelo para no atributo de renderização / atualização
Como funciona sob as cobertas
Isso tudo é especificado como "expressão de pesquisa" no UIComponent#findComponent()
javadoc :
Uma expressão de pesquisa consiste em um identificador (que corresponde exatamente à propriedade id de a UIComponent
ou em uma série desses identificadores vinculados pelo UINamingContainer#getSeparatorChar
valor do caractere. O algoritmo de pesquisa deve operar da seguinte maneira, embora alogritmos alternativos possam ser usados desde que resultado final é o mesmo:
- Identifique
UIComponent
qual será a base da pesquisa, parando assim que uma das seguintes condições for atendida:
- Se a expressão de pesquisa começar com o caractere separador (chamado de expressão de pesquisa "absoluta"), a base será a raiz
UIComponent
da árvore de componentes. O caractere separador principal será retirado e o restante da expressão de pesquisa será tratado como uma expressão de pesquisa "relativa", conforme descrito abaixo.
- Caso contrário, se este
UIComponent
é um NamingContainer
que vai servir de base.
- Caso contrário, procure os pais deste componente. Se um
NamingContainer
for encontrado, será a base.
- Caso contrário (se não
NamingContainer
for encontrado), a raiz UIComponent
será a base.
- A expressão de pesquisa (possivelmente modificada na etapa anterior) agora é uma expressão de pesquisa "relativa" que será usada para localizar o componente (se houver) que possui um ID correspondente, no escopo do componente base. A partida é realizada da seguinte maneira:
- Se a expressão de pesquisa for um identificador simples, esse valor será comparado à propriedade id e, recursivamente, através das facetas e filhos da base
UIComponent
(exceto que, se um descendente NamingContainer
for encontrado, suas próprias facetas e filhos não serão pesquisados).
- Se a expressão de pesquisa incluir mais de um identificador separado pelo caractere separador, o primeiro identificador será usado para localizar a
NamingContainer
pelas regras no marcador anterior. Em seguida, o findComponent()
método NamingContainer
será chamado, passando o restante da expressão de pesquisa.
Observe que o PrimeFaces também adere à especificação JSF, mas o RichFaces usa "algumas exceções adicionais" .
"reRender" usa o UIComponent.findComponent()
algoritmo (com algumas exceções adicionais) para encontrar o componente na árvore de componentes.
Essas exceções adicionais não são descritas em nenhum lugar em detalhes, mas sabe-se que os IDs de componentes relativos (ou seja, aqueles que não estão começando com :
) não são apenas pesquisados no contexto do pai mais próximo NamingContainer
, mas também em todos os outros NamingContainer
componentes na mesma exibição (o que é relativamente trabalho caro a propósito).
Nunca use prependId="false"
Se tudo isso ainda não funcionar, verifique se você não está usando <h:form prependId="false">
. Isso falhará durante o processamento do envio e renderização do ajax. Consulte também esta pergunta relacionada: UIForm com prependId = "false" quebra <f: ajax render> .
Fazendo referência à rodada de iteração específica dos componentes de iteração
Foi por muito tempo, não é possível fazer referência a um específico iterated item na iteração componentes como <ui:repeat>
e <h:dataTable>
assim:
<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>
No entanto, desde o Mojarra 2.2.5, o <f:ajax>
começou a apoiá-lo (ele simplesmente parou de validá-lo; portanto, você nunca mais enfrentaria a exceção mencionada na pergunta; outra correção de aprimoramento está planejada para isso posteriormente).
Isso ainda não funciona nas versões atuais do MyFaces 2.2.7 e PrimeFaces 5.2. O suporte pode vir nas versões futuras. Enquanto isso, sua melhor aposta é atualizar o componente de iteração, ou um pai, caso ele não renderize HTML, como <ui:repeat>
.
Ao usar o PrimeFaces, considere Pesquisar expressões ou seletores
O PrimeFaces Search Expressions permite que você faça referência a componentes via expressões de pesquisa em árvore de componentes JSF. O JSF possui vários embutidos:
@this
: componente atual
@form
: pai UIForm
@all
: documento inteiro
@none
: nada
O PrimeFaces aprimorou isso com novas palavras-chave e suporte à expressão composta:
@parent
: componente pai
@namingcontainer
: pai UINamingContainer
@widgetVar(name)
: componente conforme identificado por widgetVar
Você também pode misturar essas palavras-chave em expressões compostas, tais como @form:@parent
, @this:@parent:@parent
, etc.
O PrimeFaces Selectors (PFS), como em, @(.someclass)
permite que você faça referência a componentes por meio da sintaxe do seletor jQuery CSS. Por exemplo, referenciando componentes com todas as classes de estilo comuns na saída HTML. Isso é particularmente útil caso você precise fazer referência a "muitos" componentes. Isso requer apenas que os componentes de destino tenham todo um ID do cliente na saída HTML (fixo ou gerado automaticamente, não importa). Consulte também Como funcionam os seletores do PrimeFaces como em update = "@ (. MyClass)"?