Это было вызвано глупой ошибкой.Как можно было бы предположить, добавленные UIComponent
действительно автоматически добавляются к ViewRoot
.Я, однако, вызывал пользовательский UIComponent
(тот, о котором я говорил в вопросе) из моего другого пользовательского UIComponent
(о котором я не упомянул, потому что я забыл, что он там был), например:
UICodeEditor:
@Override
public void encodeAll(FacesContext context) throws IOException {
UIEditPanel editor = new UIEditPanel();
editor.encodeAll(context);
}
Затем вызывается в шаблоне, например:
<!-- codeEditor is taghandler for UICodeEditor -->
<x:codeEditor />
Здесь UICodeEditor делает автоматически добавленным к ViewRoot
однако UIEditPanel внутри этого не делает, потому что я просто звонил encodeAll(context)
, и поэтому UIEditPanel не может узнать своего «родителя».Быстрое решение состоит в том, чтобы вручную установить родительский элемент для дочернего компонента:
editor.setParent(this);
Альтернативный подход (может быть, лучше) заключался бы в расширении с UIComponentBase
(как мы обычно делаем), а не в ручной вызов encodeAll(context)
но просто добавьте компонент в качестве дочернего элемента с getChildren.add(...)
в encodeBegin(...)
, а не в encodeAll(...)
:
@Override
public void encodeBegin(FacesContext context) throws IOException {
UIEditPanel editor = new UIEditPanel();
getChildren().add(editor);
}
getChildren().add()
внутренне добавляет текущий компонент в качестве родительского для дочерних элементов.
Учитывая расположение дочернего объекта, может быть лучше построить их прямо в конструкторе и вообще не переопределять методы encodeXXX
, если нет необходимости использовать ResponseWriter
(если есть, то вынужно переопределить те).Тем не менее, это более гибкий способ переопределить и вручную вызывать кодировку, что бы вам ни понадобилось.
Также обратите внимание, что пользовательский UIComponent не может быть непосредственно целью <f:ajax render=
, поскольку он не представлен элементом DOM вДерево DOM.Это тот же случай, что и с составными компонентами, где я склоняюсь к реализации составного компонента в JSF-файл, управляемый panelGroup
, так что содержимое может быть перерисовано позже.