O código a seguir é inspirado nos Tutoriais do PrimeFaces DataGrid + DataTable e colocado em um <p:tab>de um <p:tabView>residente em um <p:layoutUnit>de a <p:layout>. Aqui está a parte interna do código (iniciando no p:tabcomponente); a parte externa é trivial.
Quando clico no <p:commandLink>, o código para de funcionar e dá a mensagem:
Não foi possível encontrar o componente com a expressão "insTable: display" referenciada em "guias: insTable: select".
Quando tento o mesmo uso <f:ajax>, ele falha com uma mensagem diferente dizendo o mesmo:
<f:ajax> contém um ID desconhecido "insTable: display" não pode localizá-lo no contexto do componente "guias: insTable: select"
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 idcomo 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 NamingContainercomponentes 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 NamingContainerpai, basta fazer referência ao seu próprio ID.
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 NamingContainercaractere separador, que é por padrão :.
NamingContainercomponentes 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_idXXXformato. 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 UIComponentem questão, também poderá verificar se ele implementa a NamingContainerinterface ou não. Por exemplo, a HtmlForm(a marca de UIComponenttrás <h:form>) mostra que ela é implementada NamingContainer, mas a HtmlPanelGroup(a marca de UIComponenttrá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 .
Então, no seu caso de:
A saída HTML gerada se <h:panelGrid id="display">parece com isso:
Você precisa usar exatamente isso idcomo ID do cliente e prefixar com o :uso em update:
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:
Ou, se este link de comando estiver dentro de um componente composto e o destino estiver fora dele:
Ou, se o link de comando e o destino estiverem dentro do mesmo componente composto:
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 UIComponentou em uma série desses identificadores vinculados pelo UINamingContainer#getSeparatorCharvalor do caractere. O algoritmo de pesquisa deve operar da seguinte maneira, embora alogritmos alternativos possam ser usados ​​desde que resultado final é o mesmo:
Identifique UIComponentqual 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 UIComponentda á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 NamingContainerque vai servir de base.
Caso contrário, procure os pais deste componente. Se um NamingContainerfor encontrado, será a base.
Caso contrário (se não NamingContainerfor encontrado), a raiz UIComponentserá 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 NamingContainerfor 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 NamingContainerpelas regras no marcador anterior. Em seguida, o findComponent()método NamingContainerserá 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 NamingContainercomponentes na mesma exibição (o que é relativamente trabalho caro a propósito).
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:
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
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)"?
@jack: Basta ler javadoc: docs.oracle.com/javaee/6/api/javax/faces/component/… Desde o JSF 2.0, ele se tornou configurável em vez de uma constante.
SEPARATOR_CHAR não está obsoleto? Você pode dar um exemplo de como chamar um componente aninhado, por exemplo: context.getViewRoot().findComponent(":inputform" + UINamingContainer.getSeparatorChar(context) + "inputtext" );Inclua também o código xhtml.
Obrigado, observe sobre a falha na renderização do ajax dentro do formulário com prependId="false"salvou meu dia.
qual é o significado exato do ID do cliente, conforme descrito em sua explicação? É o mesmo que em JSF -> "O identificador do lado do cliente para este componente". cumprimentos + obrigado pelo seu trabalho.
@ antonu17: Como indicado na resposta, ele é suportado apenas no f: ajax de Mojarra.
Em primeiro lugar: até onde eu sei, colocar a caixa de diálogo dentro de uma tabview é uma prática ruim ... é melhor retirá-la ...
e agora a sua pergunta:
desculpe, demorei um pouco para conseguir o que exatamente você queria implementar,
fiz no meu aplicativo da web agora mesmo, e funciona
como eu disse antes, coloque a caixa de diálogo p: ao lado do `p: tabView,
deixe a caixa de diálogo p: como você sugeriu inicialmente:
e o link p: commandlink deve ficar assim (tudo o que fiz foi mudar o atributo update)
o mesmo funciona no meu aplicativo da web e, se não funcionar para você, acho que há algo errado no seu código java bean ...
Eu recomendo que você tente as outras mudanças que eu escrevi na minha resposta (com a ligação e faces-config e outros ...) esta supor para resolver o seu "INFO: Não é possível encontrar compone ..."
Tentei novamente implementar sua segunda sugestão, mas ela ainda não está funcionando. A caixa de diálogo é aberta, mas não contém os dados do item selecionado. O log exibe "Não é possível encontrar o componente com o identificador" j_idt31 "na exibição" e não consigo depurar mais do que isso.
É porque a guia também é um contêiner de nomes ... sua atualização deve ser update="Search:insTable:display"O que você também pode fazer é colocar sua caixa de diálogo fora do formulário e ainda dentro da guia, então seria:update="Search:display"
— Lyrion
Tente mudar update="insTable:display"para update="display". Eu acredito que você não pode prefixar o ID com o ID do formulário assim.
— Mr.J4mes
Resposta muito antiga, mas enganosa. Consulte a publicação do BalusC acima, mostrando claramente o prefixo do ID de um componente com o ID do formulário anexo: <h: form id = "form"> <p: commandLink update = ": otherform: result"> <! - OK! -> </ h: form> <h: form id = "otherform"> <h: panelGroup id = "result" /> </ h: form> #
— J: Slick
Eu sei que isso já tem uma ótima resposta da BalusC, mas aqui está um pequeno truque que eu uso para fazer com que o contêiner me diga o clientId correto .
Remova a atualização do seu componente que não está funcionando
Coloque um componente temporário com uma atualização falsa no componente que você estava tentando atualizar
Na página, o erro de exceção do servlet informará o ID do cliente correto que você precisa fazer referência.
Remova o componente falso e coloque o clientId correto na atualização original
Aqui está um exemplo de código, pois minhas palavras podem não descrevê-lo melhor.
Remova a atualização com falha neste componente
Adicione um componente ao componente do ID que você está tentando atualizar usando uma atualização que falhará
Acesse esta página e veja o erro. O erro é: javax.servlet.ServletException: Não foi possível encontrar o componente da expressão "BogusUpdate" referenciado nas guias: insTable: BogusButton
Portanto, o clientId correto a ser usado seria o negrito mais o ID do contêiner de destino (exibido neste caso)