Как получить доступ к брату составного компонента через clientId

У меня есть составной компонент, который связывает некоторые поля ввода. Компонент будет использоваться на странице несколько раз и содержит кнопку для копирования значений другого из этих компонентов. Для этого мне нужно получить доступ к одному из этих братьев и сестер через его clientId в качестве цели для

<f:ajax execute=":XXX:siblingId" render="...">

Моя проблема заключается в создании этого идентификатора. У меня есть имя брата и я могу убедиться, что он находится в том же контейнере именования, что и компонент, содержащий кнопку копирования, но я не могу контролировать всю иерархию вложений, поэтому это может быть :form:foo:bar:parent:child или просто form:parent:child, По сути, я хотел бы получить префикс текущего составного компонента, но без собственного идентификатора компонента, а затем прикрепить идентификатор компонента, из которого необходимо скопировать.

Это похоже на эти вопросы:

Однако в обоих ответах используются отдельные функции 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"
Другие вопросы по тегам