【发布时间】: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