Вот моя (упрощенная) проблема:
У меня есть страница, которая использует 2 моих составных компонента:
- CCSelection
- CCDisplay
В CCSelection у меня есть список значений, каждое из которых имеет h: commandLink на.
При нажатии на ссылку компонент CCDiaplay обновляется с использованием выбранного значения.
Для этого CCSelection предоставляет атрибут метода, который напрямую связан с каждым h: commandLink. Значение присваивается методу с использованием атрибута f:.
В компоненте поддержки страницы у меня есть метод (который присваивается CCSelection в качестве атрибута), который устанавливает член.
CCDisplay получает это значение через атрибут cc: через средство получения члена страницы.
Это работает!
Теперь я хочу изменить это поведение.
Я попытался поместить f: ajax для каждого h: commandLink в CCSelection ... но если я добавлю @form или @all в атрибут render, ничто не будет отображено (но методы установки вызваны). Если я помещаю идентификатор UIComponent (страницы) для рендеринга, я получаю nullpointerexception, говоря, что свойство не определено для NamingContainer в CCDisplay. Довольно странно, потому что я ничего не изменил в CCDisplay!
Я думаю, что решение состоит в том, чтобы поместить f: ajax не в CCSelection, а в страницу.
Таким образом, может быть 2 способа достичь этого:
- CCSelection вызывает событие f: ajax может управлять ... но как?
- Использование cc: clientBehaviour для CCSelection. Но возможно ли нацеливание более чем на один
компонент (у меня много h: commandLink, но я хочу только 1 событие).
- Другие способы?
Вот псевдокод
page.xhtml
<myComp:ccSelection actionMethod="#{pageBean.select}"
render="#{clientIDHelper.clientId['display']}" />
<h:panelGroup id="diplay" binding="#{clientIDHelper.bindings['display']}">
<myComp:ccDisplay value="#{pageBean.value}" />
</h:panelGroup>
Чтобы восстановить полную клиентскую панель, содержащую составной компонент ccDiaplay, я использую метод clientIDMap, описанный здесь .
PageBean.java
private String _value;
public String getValue() { return _value; }
public void setValue(String value) [ _value = value; }
public void select(String value) {
setValue(value);
}
ccSelection.xhtml
<cc:interface>
<cc:attribute method-signature="void selectAction(String)"
name="actionMethod" />
<cc:attribute name="render" />
</cc:interface>
<cc:implementation>
<t:dataTable value="#{cc.values}"
var="val"
...
>
<h:column>
<t:commandLink actionListener="#{cc.selectionValueListener}"
<f:ajax render="#{cc.attrs.render}" />
<f:attribute name="value"
value="#{val}" />
</t:commandLink>
</h:column>
</t:dataTable>
</cc:implementation>
ccSelection.java
public void selectionValueListener() {
// recover the attribute value
String value = event.getComponent().getAttributes().get("value");
// call the callback method of the page
FacesContext context = FacesContext.getCurrentInstance();
MethodExpression method = (MethodExpression) this.getAttributes().get("actionMethod");
if (method != null)
method.invoke(context.getELContext(), new Object[] {value});
}
Я не думаю, что ccDisplay интересен.
Итак, если я не добавлю тег f: ajax, это сработает.
Когда я помещаю f: ajax с рендером, указывающим на clientId, переданный в параметре, я получаю ошибку при загрузке страницы.
Если я изменяю рендер для @form или @all, вызывается метод pageBean.select, но ccDisplay не обновляется.