自定义呈现程序未触发ajax事件的侦听器
再次向JSF大师问好 我正在寻找有关自定义渲染器和ajax处理程序的帮助。我们的项目不能使用正常的单选按钮和复选框渲染器,因为它们在表中渲染,这违反了我们的公司标准。我们也不能使用第三方组件库 我们有一个自定义的渲染器,我们已经在一些项目中使用,现在可以正常工作。然而,在这个特定的项目中,我需要为一些单选按钮呈现ajax单击处理程序。按照回答中的建议,我添加了对RenderKitUtils.renderSelectOnclick的调用;虽然它看起来与标准渲染器呈现相同的javaScript,而且firebug网络面板确实显示了传出的请求,但我的值更改侦听器没有被激发,我正在寻求帮助,以了解它为什么能够与标准渲染器完美地激发 一些代码: 首先,通过编程创建ajax处理程序单选按钮自定义呈现程序未触发ajax事件的侦听器,ajax,jsf,jsf-2,broadcast,custom-renderer,Ajax,Jsf,Jsf 2,Broadcast,Custom Renderer,再次向JSF大师问好 我正在寻找有关自定义渲染器和ajax处理程序的帮助。我们的项目不能使用正常的单选按钮和复选框渲染器,因为它们在表中渲染,这违反了我们的公司标准。我们也不能使用第三方组件库 我们有一个自定义的渲染器,我们已经在一些项目中使用,现在可以正常工作。然而,在这个特定的项目中,我需要为一些单选按钮呈现ajax单击处理程序。按照回答中的建议,我添加了对RenderKitUtils.renderSelectOnclick的调用;虽然它看起来与标准渲染器呈现相同的javaScript,而且
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中使用。你可以把它放在里面。