如何从复合组件外部设置复合组件的值

时间:2015-07-14 17:22:07

标签: jsf jsf-2 facelets composite-component

所以,我有一个复合组件。在其中,我有一个常规的文本输入,使用复合组件的一个属性作为值。

<h:inputTextarea id="#{cc.attrs.id}Text" value="#{cc.attrs.value}">
    <f:ajax event="blur" listener="#{someBean.onBlur}" />
</h:inputTextarea>

如您所见,我在文本框中有一个事件。此事件将打开一个弹出窗口,并使用复合控件上的文本填充它。它还保存对调用它的复合控件的引用。让我告诉你:

public void onBlur(AjaxBehaviorEvent event) {
    this.fieldReference = (UIInput) event.getSource();

    this.formula = this.fieldReference.getValueExpression("value")
            .getValue(FacesContext.getCurrentInstance().getELContext())
            .toString();

    this.displayPopup = true;
}

到目前为止,这么好。现在,当我尝试关闭弹出窗口然后使用在弹出窗口中输入的值更新复合组件上的值时,就会出现问题。我试着这样做:

public void accept(ActionEvent event) {
    this.fieldReference
            .getValueExpression("value")
            .setValue(FacesContext.getCurrentInstance().getELContext(), this.formula);
    this.displayPopup = false;
}

当我尝试时,我得到:

javax.el.PropertyNotFoundException: //C:/myProject/Path/compositeComponentPage.xhtml at line 22 and column 183 value="#{cc.attrs.value}": Target Unreachable, identifier 'cc' resolved to null

在我看来,该请求的EL上下文是不同的,因此无法解析复合组件表达式中的变量...但是如果我尝试也从复合组件中存储对ELContext对象的引用组件的请求(在onBlur()方法上),然后当我尝试在accept()中使用它时,我得到:

javax.faces.event.AbortProcessingException: java.lang.IllegalStateException: Error the FacesContext is already released!

使用MyFaces 2.0.2(WebSphere 8.5附带的版本,我相信他们会对其进行修改)和RichFaces 4.2.3。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

好吧,我似乎找到了解决方案。环顾四周,我发现这一小部分知识完全不相关article on BalusC's blog

  

支持组件实例的生命周期基本上只有一个   HTTP请求。这意味着它在每个HTTP上重新创建   请求,就像请求作用域的托管bean一样。

因此,保存对组件的引用是一件非常糟糕的事情。相反,我保存了组件的客户端ID,并在关闭弹出窗口时进行了查找,然后使用了先前没有工作的setValue。像这样:

public void onBlur(AjaxBehaviorEvent event) {
    UIInput component = (UIInput) evento.getSource();
    this.componentId = component.getClientId(FacesContext.getCurrentInstance());

    this.formula = component.getValueExpression("value")
        .getValue(FacesContext.getCurrentInstance().getELContext())
        .toString();

    this.displayPopup = true;
}

public void accept(ActionEvent evento) {
    UIInput component = (UIInput) FacesUtil.findComponent(this.componentId);
    component.setValue(this.formula);

    this.displayPopup = false;
}

所以...我猜谢谢,BalusC,你又救了一天!! :)