自定义呈现程序未触发ajax事件的侦听器

自定义呈现程序未触发ajax事件的侦听器,ajax,jsf,jsf-2,broadcast,custom-renderer,Ajax,Jsf,Jsf 2,Broadcast,Custom Renderer,再次向JSF大师问好 我正在寻找有关自定义渲染器和ajax处理程序的帮助。我们的项目不能使用正常的单选按钮和复选框渲染器,因为它们在表中渲染,这违反了我们的公司标准。我们也不能使用第三方组件库 我们有一个自定义的渲染器,我们已经在一些项目中使用,现在可以正常工作。然而,在这个特定的项目中,我需要为一些单选按钮呈现ajax单击处理程序。按照回答中的建议,我添加了对RenderKitUtils.renderSelectOnclick的调用;虽然它看起来与标准渲染器呈现相同的javaScript,而且

再次向JSF大师问好

我正在寻找有关自定义渲染器和ajax处理程序的帮助。我们的项目不能使用正常的单选按钮和复选框渲染器,因为它们在表中渲染,这违反了我们的公司标准。我们也不能使用第三方组件库

我们有一个自定义的渲染器,我们已经在一些项目中使用,现在可以正常工作。然而,在这个特定的项目中,我需要为一些单选按钮呈现ajax单击处理程序。按照回答中的建议,我添加了对RenderKitUtils.renderSelectOnclick的调用;虽然它看起来与标准渲染器呈现相同的javaScript,而且firebug网络面板确实显示了传出的请求,但我的值更改侦听器没有被激发,我正在寻求帮助,以了解它为什么能够与标准渲染器完美地激发

一些代码: 首先,通过编程创建ajax处理程序单选按钮

          AjaxBehavior valueChangeAction = (AjaxBehavior) FacesUtils.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);

        valueChangeAction.addAjaxBehaviorListener(new ProbeQuestionListener(currentQuestion, "probeDiv" + questionNumber,
            probeDiv));

        selectUI.addClientBehavior("valueChange", valueChangeAction);
        valueChangeAction.setRender(Collections.singletonList("probeDiv" + questionNumber));
使用标准渲染器,这将生成:

<table id="answer_1" class="marginLeft1a">
  <tbody>
    <tr>
      <td>
        <input id="answer_1:0" type="radio" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" value="0" name="answer_1">
        <label for="answer_1:0"> Yes</label>
      </td><td>
         <input id="answer_1:1" type="radio" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" value="1" name="answer_1">
         <label for="answer_1:1"> No</label>
     </td>
  </tr>
更新:我的渲染器基类中的解码方法是:

    @Override
public void decode(final FacesContext p_context, final UIComponent p_component) {

    final Map<String, String> valuesMap = p_context.getExternalContext().getRequestParameterMap();

    final UIInput input = (UIInput) p_component; // NOSONAR

    final Object value = valuesMap.get(input.getClientId(p_context));
    // System.out.println("radio button decode: found " + value);
    input.setSubmittedValue(value);
}
这表现为:

<span class="marginLeft1a" id="answer_1">
    <label for="answer_1:0">
    <input type="radio" value="0" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" name="answer_1" id="answer_1:0"> 
     Yes
     </label>
     <label for="answer_1:1">
       <input type="radio" value="1" onclick="mojarra.ab(this,event,'valueChange',0,'probeDiv2')" name="answer_1" id="answer_1:1"> 
       No
     </label>
</span>
如您所见,javaScript单击处理程序是相同的,输入标记的名称和id属性值也是相同的。尽管这会触发Ajax请求,但侦听器并不像第一个版本那样在服务器端启动

有什么想法吗?

的方法或者如果没有渲染器,应该基于javax.faces.behavior.event请求参数解码ajax请求,并在匹配的客户端行为上触发

基本上,逻辑如下:

Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();

if (!behaviors.isEmpty()) {
    Map<String, String> params = context.getExternalContext().getRequestParameterMap();
    String behaviorEvent = params.get("javax.faces.behavior.event");

    if (behaviorEvent != null) {
        List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);

        if (behaviorsForEvent != null && !behaviorsForEvent.isEmpty()) {
           String behaviorSource = params.get("javax.faces.source");

           if (isBehaviorSource(context, behaviorSource, component.getClientId())) {
               for (ClientBehavior behavior: behaviorsForEvent) {
                   behavior.decode(context, component);
               }
           }
        }
    }
}
鉴于您使用的是RenderKittils,并且生成的HTML输出包含mojarra.ab,我假设您使用的是mojarra。那样的话也许更明智的做法是从中扩展自定义渲染器,因为它已经在中实现了所有这些逻辑,因此您不需要重新发明轮子。

或者如果没有渲染器,则的方法应该基于javax.faces.behavior.event请求参数和匹配客户端上的触发器来解码ajax请求行为

基本上,逻辑如下:

Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();

if (!behaviors.isEmpty()) {
    Map<String, String> params = context.getExternalContext().getRequestParameterMap();
    String behaviorEvent = params.get("javax.faces.behavior.event");

    if (behaviorEvent != null) {
        List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);

        if (behaviorsForEvent != null && !behaviorsForEvent.isEmpty()) {
           String behaviorSource = params.get("javax.faces.source");

           if (isBehaviorSource(context, behaviorSource, component.getClientId())) {
               for (ClientBehavior behavior: behaviorsForEvent) {
                   behavior.decode(context, component);
               }
           }
        }
    }
}

鉴于您使用的是RenderKittils,并且生成的HTML输出包含mojarra.ab,我假设您使用的是mojarra。在这种情况下,也许更明智的做法是从中扩展自定义渲染器,因为它已经在中实现了所有这些逻辑,所以您不需要重新发明轮子。

decode方法负责查找ajax事件并将其排队。但是,我没有在您的代码片段中看到这一点。我认为你实际上一个都没有,因此你面临这个问题,这是对的吗?在任何情况下,您的自定义渲染器从哪个超类扩展而来?哦,我的错。我已经更新了问题以显示解码方法。我想我需要一些事件代码,嗯?救命啊!decode方法负责查找ajax事件并将其排队。但是,我没有在您的代码片段中看到这一点。我认为你实际上一个都没有,因此你面临这个问题,这是对的吗?在任何情况下,您的自定义渲染器从哪个超类扩展而来?哦,我的错。我已经更新了问题以显示解码方法。我想我需要一些事件代码,嗯?救命啊!看起来很有希望,但是isBehaviorSourcecontext、behaviorSource、component.getClientId返回false,因为behaviorSource是answer_1:0,clientId是answer_1-我试图在调试中逐步完成正常的渲染器,以了解其工作原理,并进一步了解自己。有趣的东西。对,最好从SelectManyCheckBox列表渲染器或RadioRenderer扩展,它实现了正确的isBehaviorSource逻辑。图例!再一次,你被证明是无价之宝!我想是时候向你表达我的谢意了,感谢你在我的JSF之旅中直接和间接地为我提供的帮助。检查你的电子邮件;如果可以的话,还有一个非常快速的例子,通过查看默认的RadioRenderer类,我看到`RequestStateManager.setcontext,RequestStateManager.TARGET\u COMPONENT\u ATTRIBUTE\u NAME,COMPONENT;`这不是我自己做的渲染器-我应该这样做吗?这是与我们没有使用的RESTAPI有关还是与更重要的东西有关?不,是用于Mojarra内部优化。这在PropertyEditorHelpergetComponent中使用。请随意保留它。看起来很有希望,但是isBehaviorSourcecontext、behaviorSource、component.getClientId返回false,因为behaviorSource是answer_1:0,clientId是answer_1-我正试图在调试中逐步完成正常的渲染器,以了解其工作原理,并进一步了解自己。有趣的东西。对,最好从SelectManyCheckBox列表渲染器或RadioRenderer扩展,它实现了正确的isBehaviorSource逻辑。图例!再一次,你被证明是无价之宝!我想是时候向你表示感谢了
在我的JSF之旅中,无论是直接的还是间接的,你们都给了我极大的帮助。检查你的电子邮件;如果可以的话,还有一个非常快速的例子,通过查看默认的RadioRenderer类,我看到`RequestStateManager.setcontext,RequestStateManager.TARGET\u COMPONENT\u ATTRIBUTE\u NAME,COMPONENT;`这不是我自己做的渲染器-我应该这样做吗?这是与我们没有使用的RESTAPI有关还是与更重要的东西有关?不,是用于Mojarra内部优化。这在PropertyEditorHelpergetComponent中使用。你可以把它放在里面。