是否可以从h:inputText标记之外的inputText字段添加验证器?
<!-- instead of this -->
<h:inputText id="field1" value="#{backingBean.field1}">
<f:validator validatorId="CustomValidator" />
</h:inputText>
<!-- something like this -->
<h:inputText id="field1" value="#{backingBean.field1}" />
<abc:validations>
<abc:validation for="field1" validator="CustomValidatorName" />
</abc:validations>
abc:validation是一个非常简短的自定义组件
<cc:interface componentType="validation">
<cc:attribute name="for" />
<cc:attribute name="validator" />
</cc:interface>
<cc:implementation>
</cc:implementation>
</ui:composition>
和面部组件类
package at.sozvers.ecm.webclient.frontend.component;
import java.io.Serializable;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
import javax.faces.validator.Validator;
@FacesComponent("validation")
public class Validation extends UIComponentBase implements NamingContainer, Serializable {
private static final long serialVersionUID = 1L;
private String for1;
private Validator validator;
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public String getFor() {
return for1;
}
public void setFor(String for1) {
this.for1 = for1;
}
public Validator getValidator() {
return validator;
}
public void setValidator(Validator validator) {
this.validator = validator;
}
}
我读到了TagHandlers和ComponentHandlers,但我不知道如何开始。
答案 0 :(得分:0)
我找到了解决方案
我创建了一个扩展ComponentHandlerWrapper的类,并覆盖onComponentPopulated方法,在那里我读取ViewMap并为每个必须验证的inputText id放置一个ValidatorSet。 ValidatorSet包含一个Set,我将FacesValidator名称写入。
public class ParentAddingComponentHandlerWrapper extends ComponentHandlerWrapper {
@Override
public void onComponentPopulated(FaceletContext ctx, UIComponent c, UIComponent parent) {
super.onComponentPopulated(ctx, c, parent);
Map<String, Object> viewMap = ctx.getFacesContext().getViewRoot().getViewMap();
if (c instanceof Validation) { // Validation is the FacesComponent class for <abc:validation>
TagAttribute uiInputName = getAttribute("for");
if (null == viewMap.get(uiInputName.getValue())) {
viewMap.put(uiInputName.getValue(), new ValidatorSet());
}
TagAttribute validator = getAttribute("validator"); // the validator attribute contains a FacesValidator name
ValidatorSet validators = (ValidatorSet) viewMap.get(uiInputName.getValue());
if (validator != null) {
validators.addValidator(validator.getValue());
}
}
}
我创建了一个CustomComponent,我在那里装饰&#34;一个inputText。我还创建了一个componentType / FacesComponent命名字段,我用@ListenerFor(systemEventClass = PreValidateEvent.class)注释了
我不得不重写我将FacesValidator添加到UIInput组件的processEvent方法
@Override
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
super.processEvent(event);
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
String id = getAttributeValue("id", "");
ValidatorSet validators = (ValidatorSet) viewMap.get(id);
if (validators != null) {
UIComponent findComponent = findComponent(id);
if (findComponent instanceof UIInput) {
UIInput input = (UIInput) findComponent;
List<Validator> inputValidators = Arrays.asList(input.getValidators());
for (Validator validator : validators.getValidators()) {
if (!doesUIInputContainsValidator(inputValidators, validator)) {
input.addValidator(validator);
}
}
}
}
}
private boolean doesUIInputContainsValidator(List<Validator> inputValidators, Validator validator) {
for (Validator inputValidator : inputValidators) {
if (inputValidator.getClass().isInstance(validator)) {
return true;
}
}
return false;
}