首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在复合实现中将f:属性传递给f:ajax侦听器

在复合实现中将f:属性传递给f:ajax侦听器
EN

Stack Overflow用户
提问于 2015-07-11 10:34:06
回答 1查看 1.2K关注 0票数 3

我有以下复合组件(只有相关代码):

代码语言:javascript
复制
    <cc:interface>
        <cc:attribute name="message" type="com.virtuafisica.business.problemsmgmt.entity.Message" required="true" />
        <cc:attribute name="notifiedListener" method-signature="void listener(javax.faces.event.AjaxBehaviorEvent)" />
   </cc:interface>

    <cc:implementation> 
        <h:selectBooleanCheckbox value="#{cc.attrs.message.notified}">
            <f:attribute name="msg" value="#{cc.attrs.message}" />
            <c:if test="#{cc.getValueExpression('notifiedListener') != null}">
                <f:ajax event="change" listener="#{cc.attrs.notifiedListener}" />
             </c:if>
        </h:selectBooleanCheckbox>   
    </cc:implementation>

这个组合是从Facelet调用的:

代码语言:javascript
复制
<my:message message="#{msg}" notifiedListener="#{problem.changeNotified}"/>

更改事件在后台bean中处理如下:

代码语言:javascript
复制
public void changeNotified(AjaxBehaviorEvent event) {
    Message message = (Message) event.getComponent().getAttributes().get("msg");
        if (message == null) {
            logger.log(Level.FINEST, "Null message!");
            return;
        }
        ....
    }

问题是支持bean中的消息是null,尽管event.getComponent()是正确的(即HTMLSelectBooleanCheckbox)。

为什么属性没有设置?

谢谢你们

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-11 11:00:53

属性被设置(您可以通过确定getValueExpression("msg")没有返回null来确认它),但是属性值只是计算null。延迟表达式是在您想要得到值的时刻计算的。因此,在ajax侦听器方法中调用#{cc.attrs.message}时,会精确地对get("msg")进行评估。然而,在那个时候,#{cc}在EL作用域中并不存在。

解决这一技术问题的方法就是手动将其放回EL范围(然后再进行清理!)

代码语言:javascript
复制
UIComponent component = event.getComponent();
UIComponent cc = UIComponent.getCompositeComponentParent(component);
Map<String, Object> requestScope = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();

try {
    requestScope.put("cc", cc);
    Message message = (Message) component.getAttributes().get("msg");
}
finally {
    requestScope.remove("cc");
}

另一个解决办法是直接从复合中获得它。

代码语言:javascript
复制
UIComponent cc = UIComponent.getCompositeComponentParent(event.getComponent());
Message message = (Message) cc.getAttributes().get("msg");

无论哪种方式,这都是相当笨拙的,因为后台bean不需要知道ajax方法是由复合调用的。简单地说,你有一个设计问题。

考虑创建一个支持组件,并从那里委托ajax调用,这样您就可以直接将Message作为方法参数传递。

代码语言:javascript
复制
@FacesComponent("yourCompositeName")
public class YourComposite extends UINamingContainer {

    public void notifiedListener(AjaxBehaviorEvent event) {
        MethodExpression notifiedListener = (MethodExpression) getAttributes().get("notifiedListener");
        Message message = (Message) getAttributes().get("message");
        notifiedListener.invoke(getFacesContext().getELContext(), new Object[] { message });
    }

}

将其注册为<cc:interface componentType>,更改method属性以接受Message参数,并让<f:ajax>调用上面支持组件上的侦听器方法,这反过来将委托给method属性。

代码语言:javascript
复制
<cc:interface componentType="yourCompositeName">
    <cc:attribute name="message" type="com.virtuafisica.business.problemsmgmt.entity.Message" required="true" />
    <cc:attribute name="notifiedListener" method-signature="void listener(com.virtuafisica.business.problemsmgmt.entity.Message)" />
</cc:interface>

<cc:implementation> 
    <h:selectBooleanCheckbox value="#{cc.attrs.message.notified}">
        <c:if test="#{cc.getValueExpression('notifiedListener') != null}">
            <f:ajax listener="#{cc.notifiedListener}" />
        </c:if>
    </h:selectBooleanCheckbox>   
</cc:implementation>

(注意:我删除了event="change",因为对于复选框/无线电按钮来说,这是错误的,默认值已经是valueChange,这是正确的值,它计算为复选框/无线电按钮的event="click" )

现在你可以把这个放在豆子里了。

代码语言:javascript
复制
public void changeNotified(Message message) {
    // ...
}  
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31356240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档