UIForm with prependId="false" breaks <f:ajax render>

У меня есть вопрос об идее того, что только UIForm получил атрибут prependId, Почему атрибут не указан в NamingContainer интерфейс? Теперь вы, вероятно, скажете, что это связано с обратной совместимостью, но я бы предпочел нарушить совместимость и позволить пользователям, которые реализуют этот интерфейс, также реализовывать методы для prependId.

Основная проблема с моей точки зрения о prependId в UIForm Суть в том, что он сломается findComponent()Я ожидаю, что если я буду использовать prependIdтогда NamingContainer Поведение может измениться не только в отношении рендеринга, но и при поиске компонентов в дереве компонентов.

Вот простой пример:

<h:form id="test" prependId="false">
  <h:panelGroup id="group"/>
</h:form>

Теперь, когда я хочу получить компонент panelGroup, я ожидаю передать строку "group" к методу findComponent(), но он ничего не найдет, я должен использовать "test:group" вместо.

Конкретная проблема в том, что при использовании ajax с prependId="false", В обновлении и обработке атрибутов тег ajax ожидает, что значения заботятся о присвоении имен контейнерам. Это немного странно, что когда я использую prependId="false" что я должен указать полный идентификатор или путь, но все в порядке.

<h:form id="test" prependId="false">
  <h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
  <h:commandButton value="go">
    <f:ajax render="test:group"/>
  </h:commandButton>
</h:form>

Хорошо, этот код будет отображаться без проблем, но он не будет обновлять PanelGroup, потому что он не может найти его. PartialViewContext будет содержать только идентификатор "group" как элемент renderIds. Я не знаю, ожидается ли это, возможно, это так, но я не знаю код. Теперь мы подошли к тому, что метод findComponent() не может найти компонент, потому что выражение, переданное в качестве параметра "group" где метод будет ожидать "test:group" найти компонент.

Одним из решений является написать свой собственный findComponent() именно так я и решил решить эту проблему. В этом методе я обрабатываю компонент, который является NamingContainer и имеет свойство prependId, установленное в false, как нормальный UIComponent, Я должен сделать это для каждого UIComponent который предлагает атрибут prependId, и это плохо. Отражение поможет обойти статическое определение типов, но это все еще не очень чистое решение.

Другим способом было бы ввести атрибут prependId в NamingContainer интерфейс и изменить поведение findComponent() работать как описано выше.

Последним предлагаемым решением будет изменение поведения тега ajax для передачи полного идентификатора, но это только решит проблему ajax, а не программные проблемы, стоящие за findComponent() реализация.

Что вы думаете об этом и почему, черт возьми, это так реализовано? У меня не может быть первой проблемы с этим, но я не смог найти связанные темы?!

1 ответ

Решение

В самом деле, UIComponent#findComponent() как сделано <f:ajax render> не удается при использовании <h:form prependId="false">, Эта проблема известна и является "не будет исправлена": проблема спецификации JSF 573.

По моему скромному мнению, они никогда не должны были добавлять prependId приписать UIForm во время JSF 1,2 века. Это было просто сделано, чтобы сохранить j_security_check пользователи, которые хотят использовать форму JSF с компонентами ввода JSF для этого (j_security_check требует точных имен полей ввода j_username а также j_password который не может быть изменен конфигурацией). Но они не совсем поняли, что во время JSF 1.2 было введено еще одно улучшение, которое позволяет вам просто продолжать использовать <form> для этого вместо того, чтобы придерживаться <h:form>, И тогда пуристы CSS/jQuery начинают злоупотреблять prependId="false" чтобы избежать экранирования символа разделителя : в их плохо выбранных селекторах CSS.

Просто не используйте prependId="false", Когда-либо.

За j_security_checkПросто используйте <form> или новый сервлет 3.0 HttpServletRequest#login(), Смотрите также Выполнение аутентификации пользователя в Java EE / JSF с использованием j_security_check.

Для селекторов CSS, если вам абсолютно необходим селектор идентификаторов (и, следовательно, не более многократно используемый селектор классов), просто оберните интересующий компонент в простой HTML <div> или же <span>,

Смотрите также:

Другие вопросы по тегам