【问题标题】:How to set the value of a composite component from outside the composite component如何从复合组件外部设置复合组件的值
【发布时间】:2015-10-03 11:38:50
【问题描述】:

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

<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。

有什么想法吗?

【问题讨论】:

  • 小问题:您是否尝试过(尝试过,不是说在生产中使用)更新的 myfaces 版本? 2.0.2 5岁
  • 你也可以用java脚本解决这个客户端,这是一个选项吗?或者设置组件引用的值(bean)并重新渲染组件。
  • @Kukeltje 不幸的是,这不是一个选项 :( 库版本是由容器强制要求的,而容器是由项目的客户端强制要求的。
  • @WvdL 设置组件引用的值正是我想要做的,不幸的是,这无法静态确定(即在编译时),因为它将用于多个地方可以编辑我的实体的各种属性。所以我需要在运行时确定我在 cc.attrs.value 上传递给组件的内容。
  • 库是 afaik,并非总是由容器强制要求。 SO上有很多关于在容器中更新JSF版本的帖子。 stackoverflow.com/questions/18141728/…。也许可以通过这种方式进行升级。我当然会调查它。

标签: jsf jsf-2 facelets composite-component


【解决方案1】:

好吧,我似乎找到了解决办法。环顾四周,我在一个完全不相关的article on BalusC's blog 中发现了这个小知识:

支持组件实例的生命周期基本上是 1 HTTP 请求。这意味着它会在每个 HTTP 上重新创建 请求,就像请求范围的托管 bean。

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

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

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

    this.displayPopup = true;
}

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

    this.displayPopup = false;
}

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

【讨论】:

    猜你喜欢
    • 2011-11-23
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 2011-06-02
    • 2017-02-13
    • 2021-06-29
    相关资源
    最近更新 更多