Как получить доступ к брату составного компонента через clientId
У меня есть составной компонент, который связывает некоторые поля ввода. Компонент будет использоваться на странице несколько раз и содержит кнопку для копирования значений другого из этих компонентов. Для этого мне нужно получить доступ к одному из этих братьев и сестер через его clientId в качестве цели для
<f:ajax execute=":XXX:siblingId" render="...">
Моя проблема заключается в создании этого идентификатора. У меня есть имя брата и я могу убедиться, что он находится в том же контейнере именования, что и компонент, содержащий кнопку копирования, но я не могу контролировать всю иерархию вложений, поэтому это может быть :form:foo:bar:parent:child
или просто form:parent:child
, По сути, я хотел бы получить префикс текущего составного компонента, но без собственного идентификатора компонента, а затем прикрепить идентификатор компонента, из которого необходимо скопировать.
Это похоже на эти вопросы:
- Как обратиться к окружающему контейнеру именования в jsf
- Как получить доступ к родительскому контейнеру именования
Однако в обоих ответах используются отдельные функции PrimeFaces, такие как @parent
а также widgetVar
, что не относится к моему проекту.
При экспериментировании с неявными объектами EL я в основном пробовал те же вещи, что и постер второго вопроса - с теми же результатами: cc.parent.clientId
всегда пусто Я тоже пробовал cc.namingContainer.clientId
а некоторые комбинации из двух, увы, - безуспешны. Особенно тот факт, что parent
не работает как положено меня смущает...
Итак: существует ли независимый от библиотеки компонентов способ доступа к "пути", содержащему контейнеры именования для составного компонента? Как parent
объект должен работать, особенно: когда мы можем его использовать, а когда нет?
PS: я думал об использовании полного clientId композита, а затем обрезал его фактический идентификатор с помощью fn:split
однако, если бы был более прямой способ, я был бы счастлив использовать его.
1 ответ
#{cc.parent}
решает в UIComponent#getCompositeComponentParent()
который возвращает ближайший родительский составной компонент. Другими словами, он возвращает только не null
когда составной компонент сам по себе вложен в другой составной компонент.
#{cc.namingContainer}
просто относится к #{cc}
сам, полностью соответствует, как указано в UIComponent#getNamingContainer()
:
Начиная с "this", вернуть ближайший компонент в предке, который является
NamingContainer
или жеnull
если ничего не может быть найдено.
Составные компоненты, а именно неявно реализуют NamingContainer
самих себя.
Так что ваши попытки, к сожалению, не сработают. Я также не вижу никаких "стандартных API" способов для достижения конкретного функционального требования. CompositeComponentAttributesELResolver
приводит к тому, что #{cc.parent}
не разрешает UIComponent#getParent()
что вы в конечном итоге хотите.
Однако вы можете предоставить UIComponent
реализация для составного, которая добавляет дополнительный получатель с уникальным именем, которое в свою очередь правильно делегирует UIComponent#getParent()
,
Вот начальный пример:
@FacesComponent("myComposite")
public class MyComposite extends UINamingContainer {
public UIComponent getParentComponent() {
return super.getParent();
}
}
Если вы зарегистрируете его следующим образом в составном интерфейсе:
<cc:interface componentType="myComposite">
тогда вы сможете использовать
#{cc.parentComponent.clientId}
получить идентификатор клиента реального родителя UIComponent
,
В конечном итоге вы должны иметь возможность использовать следующую конструкцию для ссылки на брата и сестру:
process=":#{cc.parentComponent.clientId}:siblingId"