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>
,