从复合

时间:2015-05-14 07:45:52

标签: jsf jsf-2 primefaces action composite-component

我有以下情况:

具有复杂JavaScript的JSF复合组件,我希望通过JavaScript部分刷新来自支持bean的新值(使用此复合组件的页面的支持bean,而不是支持组件@FacesComponent )。 我不想进行全面更新,因为它是一个复杂的JavaScript插件,它将无法接受地打破UX

我使用Primefaces&#39; <p:remoteCommand>通过回调来获取支持组件@FacesComponent的值Best method for passing Data from Java/JSF2 bean to Javascript/jQuery Components

我知道它有些滥用JSF,但是想将所有功能封装在一个单元中并且不要混淆JAX-RS如果你可以建议另一个好的解决方案如何封装了这样复杂的jQuery插件(为了清楚起见,我们正在谈论FullCalendar,我知道Primefaces有自己的这个组件的实现,但是它的功能不足以满足我的需求,所以,我需要自己实现)与参数的ajax回调高度相关,非常欢迎您在这里分享。

我的问题是如何使用JavaScript从支持bean更新支持组件@FacesComponent中的值?目前我参与了以下一系列活动:

  1. 从Javascript <p:remoteCommand>调用参数,该参数传递给支持组件@FacesComponent,稍后将在AjaxBehaviorEvent

    中调度

    的JavaScript

           refreshEvents([
                  {name:'start', value:start.format()}, 
                  {name:'end', value:end.format()}
           ]);
    

    JSF代码

     <p:remoteCommand name="refreshValues" oncomplete="loadValues()"  action="#{cc.refreshLocal()}" process="@this"/>
    

    我通过

    传递存储在支持组件中的参数
    getStateHelper().put(...);
    
  2. 通过以下JavaScript代码从复合组件调度jQuery事件:

        var hiddenField = $(document.getElementById(variables.hiddenId));
        hiddenField.trigger("keypress");
    
  3. 在复合组件的重写方法public void queueEvent(FacesEvent event)中,我添加了之前存储的AjaxBehaviorEvent属性,在第一步中将其向前发送。

  4. 来自复合组件的调度事件&#34;已捕获&#34;在复合组件嵌套并在此组件上执行process的页面中:

    <p:ajax event="refreshEvent" process="@this"  listener="#{bean.refreshEvents}"/>
    

    #{bean.refreshEvent}方法中,我对@EJB bean执行请求并加载数据。

  5. loadValues()

    再次调用的第1步回调中

    <p:remoteCommand name="loadValues" action="#{cc.getLocalData()}" oncomplete="updateValues(xhr, status, args);"/>

  6. 在支持组件的方法#{cc.getLocalData()}中,我使用以下方法添加回调参数:

    RequestContext.getCurrentInstance().addCallbackParam("param", ...);

  7. 来自第5步的updateValues(xhr, status, args)功能获取args此参数的值并执行实际更新。

  8. 所以,我的一般问题是可以简化这个过程以及如何?

    谢谢。

1 个答案:

答案 0 :(得分:2)

这确实有点过于复杂。共有3个ajax请求只执行一个动作,一个支持组件通过视图状态向前和向后传递数据。

您的主要目标似乎是能够将bean操作方法声明为复合组件属性,然后应该由复合内部的<p:remoteCommand>调用,并根据传入的参数返回所需的模型实体,最好是一些预处理和后处理。

您可以在复合接口中使用<cc:attribute method-signature>来声明方法表达式属性:

<cc:interface componentType="yourComposite">
    <cc:attribute name="eventListener" method-signature="com.example.Entity method(java.lang.String, java.lang.String)" required="true" />
</cc:interface>

可以在模板客户端中使用,如下所示:

<my:composite ... eventListener="#{bean.eventListener}" />
public Entity eventListener(String start, String end) {
    // ...
    return entity;
}

复合实现可能如下所示:

<cc:implementation>
    ...
    <p:remoteCommand name="refreshEvents" 
        process="@this" action="#{cc.processEventListener}"
        oncomplete="updateValues(xhr, status, args)" />
    ...
</cc:implementation>

#{cc.processEventListener}方法可以将eventListener属性作为MethodExpression获取并按以下方式调用,以及一些预处理和后处理:

public void processEventListener() {
    String start = getRequestParameter("start");
    String end = getRequestParameter("end");
    // ...
    MethodExpression method = (MethodExpression) getAttributes().get("eventListener");
    Entity entity = (Entity) eventListener.invoke(getFacesContext().getELContext(), new Object[] { start, end });
    // ...
    addCallbackParam("param", entityAsJSON);
}

现在只有1个ajax请求“像往常一样”。