JSF2 Композитный компонент ссылка с использованием ajax - PullRequest
1 голос
/ 28 октября 2011

Вот моя (упрощенная) проблема:
У меня есть страница, которая использует 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 не обновляется.

Ответы [ 2 ]

1 голос
/ 29 октября 2011

Я думаю, что вижу небольшую ошибку в page.xhtml.Посмотрите, когда вы создали компонент cc: display, вы сказали:

<cc:attribute method-signature="void selectAction(String)" name="actionMethod" />

Это означает, что параметр необходим.

Но когда вы вызываете его в page.xhtml, вы делаете это:

<myComp:ccSelection actionMethod="#{pageBean.select}"...

И метод его поддерживающего компонента:

public void select(String value) {
  setValue(value);
}

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

Чтобы исправить это, я думаю, что вы должны передать значение как:

<myComp:ccSelection actionMethod="#{pageBean.select(???Selected value

???)}"...
0 голосов
/ 31 октября 2011

OK. Это решаемо ... но мне это не очень нравится.
Вы будете думать, что я дурак: я решил проблему, удалив <! [CDATA, окружающий мои сценарии! <Br /> Я уже нашел некоторые проблемы с использованием CDATA. Я не знаю, является ли это ошибкой MyFaces или что-то, что я делаю неправильно, например, помещая много блоков h: outputScript с CDATA в составные компоненты, но с CDATA я получаю ошибки или не работаю. Просто удалив его, он работает!

...