UIForm com prependId = quebra “falsa”

Eu tenho uma pergunta sobre a ideia por trás do fato de que apenas o UIForm tem o atributo prependId . Por que o atributo não está especificado na interface NamingContainer ? Agora você provavelmente dirá que é por causa da compatibilidade com versões anteriores, mas eu preferiria quebrar a compabilidade e permitir que os usuários que implementam essa interface também implementem methods para a coisa prependId.

O principal problema da minha perspectiva sobre o prependId no componente UIForm é que ele quebrará findComponent() Eu esperaria que, se eu usasse prependId , o comportamento NamingContainer mudaria, não apenas relacionado à renderização, mas também ao querer procurar por componentes na tree de componentes.

Aqui um exemplo simples:

    

Agora, quando eu quero obter o componente panelGroup eu esperaria passar a string "group" para o método findComponent() , mas não vai encontrar nada, eu tenho que usar "test:group" lugar.

O problema concreto disso é quando usamos ajax com prependId="false" . A tag ajax espera na atualização e no processo de atributos, que os valores se preocupem em nomear contêineres. É um pouco estranho que, quando eu uso prependId="false" eu tenha que especificar o id ou caminho completo, mas tudo bem.

         

Bem, esse código será renderizado sem problemas, mas não atualizará o panelGroup porque não pode encontrá-lo. O PartialViewContext irá conter apenas o id "group" como elemento do renderIds. Eu não sei se isso é esperado, provavelmente é, mas eu não sei o código. Agora chegamos ao ponto em que o método findComponent() não pode encontrar o componente porque a expressão passada como parâmetro é "group" onde o método esperaria que "test:group" encontrasse o componente.

Uma solução é escrever seu próprio findComponent() que é a maneira que eu escolhi para lidar com esse problema. Neste método, eu manipulo um componente que é um NamingContainer e tem a propriedade prependId configurada como false, como um UIComponent normal. Eu terei que fazer isso para cada UIComponent que ofereça um atributo prependId e que seja ruim. A reflection ajudará a contornar a definição estática de tipos, mas ainda não é uma solução realmente limpa.

A outra maneira seria introduzir o atributo prependId na interface NamingContainer e alterar o comportamento de findComponent() para funcionar como descrito acima.

A última solução proposta seria alterar o comportamento da tag ajax para passar o ID inteiro, mas isso só resolveria o problema do ajax e não os problemas programáticos por trás da findComponent() do findComponent() .

O que você acha sobre isso e por que diabos é implementado assim? Não posso ser o primeiro a ter este problema, mas não consegui encontrar tópicos relacionados ?!

De fato, UIComponent#findComponent() como feito por falha ao usar . Esse problema é conhecido e é um “Não vai consertar”: edição de especificação JSF 573 .

Na minha humilde opinião, eles nunca deveriam ter adicionado o atributo prependId ao UIForm durante as idades do JSF 1.2. Isso foi feito apenas para manter os usuários do j_security_check felizes que gostariam de usar um formulário JSF com componentes de input JSF para isso ( j_security_check requer nomes de campos de input exatos j_username e j_password que não puderam ser modificados pela configuração). Mas eles não perceberam exatamente que, durante o JSF 1.2, outra melhoria foi introduzida, o que permite que você continue usando o

para isso, em vez de seguir para . E então os puristas de CSS / jQuery começam a abusar de prependId="false" para evitar o escape do caractere separador : em seus seletores CSS mal escolhidos.

Apenas não use prependId="false" , nunca.

Para j_security_check , apenas use

ou o novo Servlet 3.0 HttpServletRequest#login() . Consulte também Execução da autenticação do usuário no Java EE / JSF usando j_security_check .

Para seletores CSS, caso você realmente precise de um seletor de ID (e, portanto, não de um seletor de class mais reutilizável), simplesmente envolva o componente de interesse em um HTML simples

ou .

Veja também:

  • Como selecionar componentes JSF usando jQuery?
  • Como usar o ID do elemento HTML gerado pelo JSF com dois pontos “:” nos seletores CSS?
  • Por padrão, o JSF gera ids inutilizáveis, que são incompatíveis com a parte css dos padrões web