PrimeFaces DataTable InCell编辑 - 非平凡的验证

Dan*_*lor 3 validation datatable jsf primefaces

我想在DataTable中使用InCell编辑和验证.我知道使用f:validator可以解决这些琐碎的验证,但是对于非平凡的名称有什么用?

我必须说,我必须确保表中的'name'属性是唯一的.因此,在接受编辑之前,我应检查名称是否已更改以及是否由其他元素使用.如果是这样,则必须拒绝编辑.

怎么实现呢?正如我所理解的那样,eventListener只会被通知接受编辑,因此理论上我可以做出反应并将其还原,但我宁愿在用户点击"接受"图标时拒绝编辑.

sie*_*z0r 6

就像Daniel说的那样,你可以使用JSF验证器.一个简短的例子:

假设我们有一个人:

public class Person
{
    // Just imagine getters and setters ;-)
    private String firstName, lastName;
}
Run Code Online (Sandbox Code Playgroud)

还有一个非常简单的支持bean:

@ManagedBean
@ViewScoped
public class PersonBean
{
    private List<Person> persons = new ArrayList<Person>();

    @PostConstruct
    private void init()
    {
        persons.add(new Person("John", "Doe"));
    }   
}
Run Code Online (Sandbox Code Playgroud)

例如,我们希望确保名字以大写字母开头.我们不关心姓氏是否以大写字母开头(因为与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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

现在要很好地展示一切:

<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>
Run Code Online (Sandbox Code Playgroud)

如果您感兴趣,可以使用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));
    }

}
Run Code Online (Sandbox Code Playgroud)

我们将要使用的注释:

@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 {};
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们声明的消息"{FirstUpper.message}"将解析为资源包.该bundle必须位于类路径的根目录中,并命名为 ValidationMessages.properties.要进行本地化,您可以添加区域设置代码:ValidationMessages_en.properties.

在该文件中声明消息:

FirstUpper.message=First name should start with a capital.
Run Code Online (Sandbox Code Playgroud)

人员班:

public class Person
{
    @FirstUpper
    private String firstName;
    private String lastName;
    // Imagine the getters/setters again ;-)
}
Run Code Online (Sandbox Code Playgroud)

现在,在您的UI中,您不必引用验证器,JSF足够聪明,可以使用JSR-303进行验证.所以不是这样的:

<p:inputText validator="firstNameValidator" value="#{person.firstName}" />
Run Code Online (Sandbox Code Playgroud)

只要用这个:

<p:inputText value="#{person.firstName}" />
Run Code Online (Sandbox Code Playgroud)

容易吗?;-)