JSF2——在f:ajax上具有可选侦听器属性的复合组件
我有一个复合组件,看起来像这样:JSF2——在f:ajax上具有可选侦听器属性的复合组件,ajax,jsf,jsf-2,listener,composite-component,Ajax,Jsf,Jsf 2,Listener,Composite Component,我有一个复合组件,看起来像这样: <!DOCTYPE html> <html xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:dm="http://davemaple.com/dm-taglib" xmlns:rich="http://richfaces.org/rich" xmlns:cc="http://java.
<!DOCTYPE html>
<html
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:dm="http://davemaple.com/dm-taglib"
xmlns:rich="http://richfaces.org/rich"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j">
<cc:interface>
<cc:attribute name="styleClass" />
<cc:attribute name="textBoxStyleClass" />
<cc:attribute name="inputTextId" />
<cc:attribute name="labelText" />
<cc:attribute name="tabindex" />
<cc:attribute name="required" default="false" />
<cc:attribute name="requiredMessage" />
<cc:attribute name="validatorId" />
<cc:attribute name="converterId" />
<cc:attribute name="title"/>
<cc:attribute name="style"/>
<cc:attribute name="unicodeSupport" default="false"/>
<cc:attribute name="tooltip" default="false"/>
<cc:attribute name="tooltipText" default=""/>
<cc:attribute name="tooltipText" default=""/>
<cc:attribute name="onfail" default=""/>
<cc:attribute name="onpass" default=""/>
</cc:interface>
<cc:implementation>
<ui:param name="converterId" value="#{! empty cc.attrs.converterId ? cc.attrs.converterId : 'universalConverter'}" />
<ui:param name="validatorId" value="#{! empty cc.attrs.validatorId ? cc.attrs.validatorId : 'universalValidator'}" />
<ui:param name="component" value="#{formFieldBean.getComponent(cc.attrs.inputTextId)}" />
<ui:param name="componentValid" value="#{((facesContext.maximumSeverity == null and empty component.valid) or component.valid) ? true : false}" />
<ui:param name="requiredMessage" value="#{! empty cc.attrs.requiredMessage ? cc.attrs.requiredMessage : msg['validation.generic.requiredMessage']}" />
<ui:param name="clientIdEscaped" value="#{fn:replace(cc.clientId, ':', '\\\\\\\\:')}" />
<h:panelGroup layout="block" id="#{cc.attrs.inputTextId}ValidPanel" style="display:none;">
<input type="hidden" id="#{cc.attrs.inputTextId}Valid" value="#{componentValid}" />
</h:panelGroup>
<dm:outputLabel for="#{cc.clientId}:#{cc.attrs.inputTextId}" id="#{cc.attrs.inputTextId}Label">#{cc.attrs.labelText}</dm:outputLabel>
<dm:inputText
styleClass="#{cc.attrs.textBoxStyleClass}"
tabindex="#{cc.attrs.tabindex}"
id="#{cc.attrs.inputTextId}"
required="#{cc.attrs.required}"
requiredMessage="#{requiredMessage}"
title="#{cc.attrs.title}"
unicodeSupport="#{cc.attrs.unicodeSupport}">
<f:validator validatorId="#{validatorId}" />
<f:converter converterId="#{converterId}" />
<cc:insertChildren />
<f:ajax
event="blur"
execute="@this"
render="#{cc.attrs.inputTextId}ValidPanel #{cc.attrs.inputTextId}Msg"
onevent="on#{cc.attrs.inputTextId}Event" />
</dm:inputText>
<rich:message for="#{cc.clientId}:#{cc.attrs.inputTextId}" id="#{cc.attrs.inputTextId}Msg" style="display: none;" />
<script>
function on#{cc.attrs.inputTextId}Event(e) {
if(e.status == 'success') {
$('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}').trigger($('##{cc.attrs.inputTextId}Valid').val()=='true'?'pass':'fail');
}
}
$('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}').bind('fail', function() {
$('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}, ##{clientIdEscaped}\\:#{cc.attrs.inputTextId}Label, ##{cc.attrs.inputTextId}Msg, ##{cc.id}Msg').addClass('error');
$('##{cc.id}Msg').html($('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}Msg').html());
#{cc.attrs.onfail}
}).bind('pass', function() {
$('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}, ##{clientIdEscaped}\\:#{cc.attrs.inputTextId}Label, ##{cc.attrs.inputTextId}Msg, ##{cc.id}Msg').removeClass('error');
$('##{cc.id}Msg').html($('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}Msg').html());
#{cc.attrs.onpass}
});
</script>
<a4j:region rendered="#{facesContext.maximumSeverity != null and !componentValid}">
<script>
$(document).ready(function() {
$('##{clientIdEscaped}\\:#{cc.attrs.inputTextId}').trigger('fail');
});
</script>
</a4j:region>
</cc:implementation>
</html>
#{cc.attrs.labelText}
#{cc.attrs.inputExtId}事件(e)上的函数{
如果(如状态=‘成功’){
$('#{clientdescaped}\\:'{cc.attrs.inputTextId}').trigger($('#{cc.attrs.inputTextId}Valid').val()='true'?'pass':'fail');
}
}
$(“##{clientdescaped}\\:#{cc.attrs.inputTextId}”).bind('fail',function(){
$(“##{clientdescaped}\\:#{cc.attrs.inputTextId},#{clientdescaped}\\:#{cc.attrs.inputTextId}标签,#{cc.attrs.inputTextId}Msg,##{cc.id}Msg').addClass('error');
$('.#{cc.id}Msg').html($('.#{clientIdEscaped}\\\:#{cc.attrs.inputTextId}Msg').html();
#{cc.attrs.onfail}
}).bind('pass',function(){
$(“##{clientdescaped}\\:#{cc.attrs.inputTextId},#{clientdescaped}\\:#{cc.attrs.inputTextId}标签,#{cc.attrs.inputTextId}Msg,##{cc.id}Msg').removeClass('error');
$('.#{cc.id}Msg').html($('.#{clientIdEscaped}\\\:#{cc.attrs.inputTextId}Msg').html();
#{cc.attrs.onpass}
});
$(文档).ready(函数(){
$(“##{clientdescaped}\\:#{cc.attrs.inputTextId}')。触发器('fail');
});
我希望能够添加一个可选的“listener”属性,如果定义了该属性,它将向我的f:ajax添加一个事件侦听器,但我很难弄清楚如何实现这一点。任何帮助都将不胜感激。您需要指定标记的
方法签名
属性,以便将属性值视为方法表达式。您可以使用JSTL视图构建时间标记
有条件地添加
标记
<cc:interface>
<cc:attribute name="listener" method-signature="void listener()" />
</cc:interface>
<cc:implementation>
<h:someComponent>
<c:if test="#{cc.getValueExpression('listener') != null}">
<f:ajax listener="#{cc.attrs.listener}" />
</c:if>
</h:someComponent>
</cc:implementation>
或者,当您的环境不支持EL 2.2时,请创建一个支持组件:
@FacesComponent("someComponent")
public class SomeComponent extends UINamingContainer {
public boolean isHasListener() {
return getValueExpression("listener") != null;
}
}
将被声明并用作
<cc:interface type="someComponent">
<cc:attribute name="listener" method-signature="void listener()" />
</cc:interface>
<cc:implementation>
<h:someComponent>
<c:if test="#{cc.hasListener}">
<f:ajax listener="#{cc.attrs.listener}" />
</c:if>
</h:someComponent>
</cc:implementation>
我也有同样的问题,我的解决方案是为action方法创建默认值。我只需要创建一个类:
MyComponent.java
,它包含所有默认的签名方法
<cc:interface>
<cc:attribute name="listener" method-signature="void listener()"
default="#{myComponent.doNothing()}" />
</cc:interface>
<cc:implementation>
<h:someComponent>
<f:ajax listener="#{cc.attrs.listener}" />
</h:someComponent>
</cc:implementation>
不幸的是,上述所有方法对我都不起作用,所以我胡思乱想,想出了以下解决方案
<cc:interface type="someComponent">
<cc:attribute name="listener" method-signature="void listener()" />
</cc:interface>
<cc:implementation>
<h:someComponent>
<p:ajax listener="#{cc.attrs.listener}" onstart="#{cc.attrs.containsKey('listener') ? '' : 'return false'}" />
</h:someComponent>
</cc:implementation>
这将始终绑定ajax行为,但仅当确实有侦听器时才执行它。ok。我已经做到了这一点,但我希望它是一个可选属性。当它不是由组件的客户端提供时,我不希望f:ajax使用它。有没有一种方法可以使它在f:ajax上成为可选的?嗯,这样不行。
试图将其解析为值表达式:/抱歉,我必须还原我的答案。确定。选项2没有一个漂亮的界面,但我想我会选择它,这样我就可以把其他的f:ajax功能隐藏起来。理论上,当使用一个“支持组件”(
)时,它应该是可行的,它有一个getter方法来检查“监听器”是否属性已定义,以便您可以使用
左右。没有办法告诉EL不要将其解析为值表达式。由于{cc.attrs}
的EL解析器,即使{not cc.attrs.containsKey('listener')}
也无法工作。我已经更新了答案。更好的是,#{notempty cc.getValueExpression('listener')}
适合我。很抱歉更新太多,这也是我第一次:)
<cc:interface type="someComponent">
<cc:attribute name="listener" method-signature="void listener()" />
</cc:interface>
<cc:implementation>
<h:someComponent>
<p:ajax listener="#{cc.attrs.listener}" onstart="#{cc.attrs.containsKey('listener') ? '' : 'return false'}" />
</h:someComponent>
</cc:implementation>