【问题标题】:JSF2 Composite component link using ajax使用 ajax 的 JSF2 复合组件链接
【发布时间】:2011-10-28 15:53:13
【问题描述】:

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

在 CCSelection 中,我有一个值列表,每个值都有一个 h:commandLink 到。
单击链接时,CCDiaplay 组件会使用所选值刷新。
为此,CCSelection 公开了一个方法属性,该属性直接链接到每个 h:commandLink。使用 f:attribute 将值赋予方法。
在页面支持 bean 中,我有一个方法(作为属性提供给 CCSelection),它设置一个成员。
CCDisplay 通过页面成员的 getter 通过 cc:attribute 获取此值。
它有效!
现在,我想 ajaxize 这种行为。

我尝试在 CCSelection 中为每个 h:commandLink 放置一个 f:ajax ...但是如果我将 @form 或 @all 放在渲染属性中,则不会渲染任何内容(但会调用 setter 方法)。如果我将 UIComponent(页面的)的 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 的渲染指向参数中传递的 clientId 时,加载页面时出现错误。 如果我更改@form 或@all 的渲染,则会调用pageBean.select 方法,但不会刷新ccDisplay。

【问题讨论】:

  • 如果我理解得很好,您怀疑如果您使用 f:ajax 标记扭曲所有组件,它应该可以工作,但是您不知道如何处理命令链接生成的事件?如果是这样,我有一个想法,您可以在您的方法中使用 '' 扭曲现有代码,尝试找到方法仅在需要时处理事件的解决方法。如果您发布一些代码或伪代码,也许我们可以提供更多帮助。
  • 其实就是用f:ajax的事件,调用方法。问题是渲染:当 render="@all" 或 render="@form" 使用 f:ajax 时,CCDisplay 不渲染。
    如果将组件的 id 放在 f:ajax 渲染中,我会得到加载页面时出错。

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


【解决方案1】:

我想我在 page.xhtml 中看到了一个小错误。 看看你创建组件时 cc:display 你说的:

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

这意味着需要一个参数。

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

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

它的backing bean方法是:

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

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

要修复它,我认为您应该以某种方式传递值:

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

???)}"...

【讨论】:

  • 感谢您的回答。据我所知,您不能像您建议的那样直接传递参数。尽管如此,当 f:ajax 不存在时它仍然有效。其实参数是通过代码传递的:method.invoke(context.getELContext(), new Object[] {value});
  • @boblemar 可以通过表达式语言将参数传递给 backingbean,但这取决于您使用的应用服务器。我使用 glassfish v3,我可以做到。无论如何,在此链接中,您可以看到传递该值的其他替代方法:mkyong.com/jsf2/…
  • 好的。我不知道。无论如何,我认为它对我的情况没有用......而且我的目标是Tomcat6。感谢您的链接。
【解决方案2】:

好的。解决了……不过我不是很喜欢。
你会认为我是个傻瓜:我通过删除围绕我的脚本的 我已经发现使用 CDATA 的一些问题。我不知道这是 MyFaces 错误还是我做错了事情,例如将许多带有 CDATA 的 h:outputScript 块放在复合组件中,但使用 CDATA,我会出错或无法正常工作。只需删除它,它就可以工作!

【讨论】:

    猜你喜欢
    • 2013-08-31
    • 2011-11-27
    • 2011-11-10
    • 2012-01-07
    • 2012-12-07
    • 2012-04-10
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多