我想在DataTable和验证中使用InCell编辑。我知道琐碎的验证可以用f:validator来解决,但是对于非琐碎的名称呢?
我必须确保'name'属性在表中是唯一的。因此,在接受编辑之前,我应该检查名称是否被更改,以及它是否被另一个元素使用。如果是,编辑必须被拒绝。
如何实现?正如我所理解的那样,eventListener只会收到编辑被接受的通知,所以理论上我可以做出反应并恢复它,但我更愿意在用户单击'accept'图标时拒绝编辑。
就像Daniel说的,您可以使用JSF验证器。一个简短的例子:
假设我们有一个人:
public class Person
{
// Just imagine getters and setters ;-)
private String firstName, lastName;
}
和一个非常简单的后台bean:
@ManagedBean
@ViewScoped
public class PersonBean
{
private List<Person> persons = new ArrayList<Person>();
@PostConstruct
private void init()
{
persons.add(new Person("John", "Doe"));
}
}
例如,我们希望确保名字以大写字母开头。我们不关心姓氏是否以大写字母开头(因为与IE或遗留数据库的兼容性,你知道,通常的奇怪)。
@FacesValidator("firstNameValidator")
public class FirstNameValidator implements javax.faces.validator.Validator
{
@Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException
{
if (!Character.isUpperCase(String.valueOf(value).charAt(0)))
{
FacesMessage msg = new FacesMessage("First name should start with a capital.");
throw new ValidatorException(msg);
}
}
}
现在显示所有内容:
<p:growl id="growl" />
<h:form>
<p:dataTable value="#{bean.persons}" var="person" editable="true">
<p:ajax event="rowEdit" update=":growl"/>
<p:column headerText="first name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{person.firstName}" />
</f:facet>
<f:facet name="input">
<p:inputText validator="firstNameValidator"
value="#{person.firstName}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="last name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{person.lastName}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{person.lastName}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column>
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
如果您感兴趣,可以通过使用bean验证(JSR-303)在域级别上配置验证。我强烈推荐它,因为它不依赖于JSF,而且它集成了JPA。
使用bean验证按承诺更新:
首先,验证器:
public class FirstNameValidator implements ConstraintValidator<FirstUpper, String>
{
@Override
public void initialize(FirstUpper constraintAnnotation) { }
@Override
public boolean isValid(String value, ConstraintValidatorContext context)
{
return Character.isUpperCase(value.charAt(0));
}
}
我们将要使用的注释:
@Constraint(validatedBy = FirstNameValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface FirstUpper
{
String message() default "{FirstUpper.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
注意,我们声明的"{FirstUpper.message}"
消息将被解析为一个资源包。bundle必须位于类路径的根目录下,名为ValidationMessages.properties
。如果需要进行本地化,可以添加区域代码:ValidationMessages_en.properties
。
在该文件中声明消息:
FirstUpper.message=First name should start with a capital.
person类:
public class Person
{
@FirstUpper
private String firstName;
private String lastName;
// Imagine the getters/setters again ;-)
}
现在,在您的UI中,您不必引用验证器,JSF足够聪明,可以使用JSR-303进行验证。所以不用这个:
<p:inputText validator="firstNameValidator" value="#{person.firstName}" />
就用这个:
<p:inputText value="#{person.firstName}" />
简单对吧?: -)