UIForm с prependId = "ложными" перерывами <f: ajax render> - PullRequest
20 голосов
/ 14 сентября 2011

У меня есть вопрос об идее того, что только 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, и это плохо.Reflection поможет обойти статическое определение типов, но это все еще не совсем чистое решение.

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

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

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

1 Ответ

18 голосов
/ 14 сентября 2011

Действительно, UIComponent#findComponent(), как сделано <f:ajax render>, терпит неудачу при использовании <h:form prependId="false">.Эта проблема известна и является «не будет устранена»: JSF spec проблема 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> или новый Servlet 3.0 HttpServletRequest#login().См. Также Выполнение аутентификации пользователя в Java EE / JSF с использованием j_security_check .

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

См. также:

...