【问题标题】:PrimeFaces DataTable InCell editing - non-trivial validationPrimeFaces DataTable InCell 编辑 - 非平凡验证
【发布时间】:2012-12-22 06:19:04
【问题描述】:

我想在 DataTable 中使用 InCell 编辑和验证。我知道可以使用 f:validator 解决琐碎的验证,但是对于非琐碎的名称呢?

比方说,我必须确保“名称”属性在表中是唯一的。因此,在接受编辑之前,我应该检查名称是否已更改以及是否被其他元素使用。如果是这样,编辑必须被拒绝。

如何实现呢?据我所知,eventListener 只会收到编辑被接受的通知,所以理论上我可以做出反应并恢复它,但我更愿意在用户点击“接受”图标时拒绝编辑。

【问题讨论】:

  • 你为什么不能在f:validator validatorId="myNonTrivialValidator" 里做呢? ,只需使用您的逻辑编写您自己的自定义验证器...
  • 这样的验证器是否可以访问给定的数据 bean 或表格内容?我认为验证者只能访问他们所在的字段
  • 此外,我们不使用 jsf 验证器,因为它们在表单级别、每次提交时都被激活,并且比自定义代码更难控制。但无论如何,jsf验证器只验证单个字段,验证可以依赖于多个字段
  • 它可以访问您的会话范围 bean,还应该访问视图 bean...

标签: validation jsf primefaces datatable


【解决方案1】:

正如 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}" 将被解析为资源包。捆绑包必须位于类路径的根目录中,名为ValidationMessages.properties。要进行本地化,您可以添加区域设置代码:ValidationMessages_en.properties。

在该文件中声明消息:

FirstUpper.message=First name should start with a capital.

人物类:

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}" />

简单吧? ;-)

【讨论】:

  • 但是,这是实体级验证器,而不是实体集级验证器,所以最简单的情况
  • Hibernate Validator 的问题(我想你指的是他)是具有 JBoss 许可证的依赖项,不能简单地在商业程序中免费使用(至少法律部门已经发现)就是这样)
  • Hibernate 验证器是 JSR-303 的实现。有多种方法,例如 Apache 公共验证(可能是 Apache 许可)和 Slring 框架。您也可以使用 vanilla JavaEE bean 验证。在包 javax.validation 中已经有一些了。
  • 我现在不能(因为我在手机上),但我稍后会写一个简短的例子。 ;-)
  • @lechlukasz 我已经更新了我的答案。免费使用,这里没有许可证;-)
猜你喜欢
  • 2012-02-21
  • 1970-01-01
  • 2013-10-21
  • 2012-10-15
  • 1970-01-01
  • 2016-10-19
  • 2014-03-08
  • 2015-01-02
  • 2014-04-12
相关资源
最近更新 更多