使用ajax的JSF2 Composite组件链接

时间:2011-10-28 15:53:14

标签: ajax jsf-2 behavior composite composite-component

这是我的(简化)问题:
我有一个页面使用了我的2个复合组件:
  - CCSelection
  - CCDisplay

在CCSelection中,我有一个值列表,每个值都有一个h:commandLink 单击链接时,将使用所选值刷新CCDiaplay组件 为此,CCSelection公开了一个直接链接在每个h:commandLink上的方法属性。使用f:属性将该值赋予方法 在页面支持bean中,我有一个方法(给予CCSelection作为属性),它设置了一个成员。
CCDisplay通过页面成员的getter通过cc:属性获取此值 它有效!
现在,我想说明这种行为
我尝试在CCSelection中为每个h:commandLink放置一个f:ajax ...但是如果我在渲染属性中放置@form或@all,则不会渲染任何内容(但会调用setter方法)。如果我将UIComponent(of Page)的id放到渲染中,我会得到一个nullpointerexception,说明没有为CCDisplay中的NamingContainer定义属性。非常奇怪,因为我没有在CCDisplay中改变任何东西!

我认为解决方案是将f:ajax放在CCSelection中但不在Page中。
因此,可能有两种方法可以实现这一目标:
  - CCSelection提出了一个事件f:ajax可以管理......但是如何?   - 使用cc:clientBehaviour进行CCSelection。但是有可能更多地定位1个组件(我有很多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复合组件的面板的完整clientid,我使用描述here的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与渲染指向传递给param的clientId时,我在加载页面时出错。 如果我更改@form或@all的渲染,则调用pageBean.select方法,但不刷新ccDisplay。

2 个答案:

答案 0 :(得分:1)

我想我在page.xhtml中看到一点错误。 看你创建组件的时间cc:显示你说:

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

这意味着需要一个参数。

但是当你在page.xhtml中调用它时,你会这样做:

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

它的支持bean方法是:

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

如您所见,支持bean是正确的,但是当您在页面中调用组件时,没有参数传递给bean,并且最后从未设置该值。 我认为这可能是其中一个原因。

要解决这个问题,我认为你应该通过以下方式传递价值:

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

???)}"...

答案 1 :(得分:0)

行。它解决了......但我不太喜欢它。
你会认为我是个傻瓜:我通过删除&lt;![CDATA围绕我的脚本来解决问题!
我已经发现使用CDATA的一些问题。我不知道这是一个MyFaces错误还是我用错误的方法,比如在复合组件中放入许多带有CDATA的h:outputScript块,但是使用CDATA,我得到错误或无法正常工作。只是删除它,它的工作原理!