用于显示列表错误的表单绑定 [英] Form binding for showing errors of a list

查看:22
本文介绍了用于显示列表错误的表单绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Product 对象,其中包含一个 Set提供者.我在 Provider 中用 @NotEmpty 注释了一个变量 url,现在我想显示一个错误,如果这个字段是空的.我不确定如何正确访问 hasErrors 方法中的字段 providers.

I've got a Product object that contains a Set<Provider> providers. I've annotated within the Provider a variable url with @NotEmpty and now I want to display a error, if this field is empty. I'm not sure how I can access the field providers within the hasErrors method properly.

表格:

<form action="#" th:action="@{/saveDetails}" th:object="${selectedProduct}" method="post">

  <!-- bind each input field to list (working) -->
  <input th:each="provider, status : ${selectedProduct.providers}"
         th:field="*{providers[__${status.index}__].url}" />

  <!-- all the time 'false' -->
  <span th:text="'hasErrors-providers=' + ${#fields.hasErrors('providers')}"></span>
  <span th:text="'hasErrors-providers[0].url=' + ${#fields.hasErrors('providers[0].url')}"></span>

  <!-- not working -->
  <span class="help-block" th:each="provider, status : ${selectedProduct.providers}" 
     th:if="${#fields.hasErrors('providers[__${status.index}__].url')}" 
     th:errors="${providers[__${status.index}__].url}">Error Url
  </span>

  <!-- print errors (just for testing purpose) -->
    <ul>
      <li th:each="e : ${#fields.detailedErrors()}">
        <span th:text="${e.fieldName}">The field name</span>|
        <span th:text="${e.code}">The error message</span>
      </li>
    </ul>

</form>

    中,我收到每个错误 providers[].url 作为 e.fieldName.我认为它会有一些索引,比如 providers[0].url 等.所以我的问题是,如何正确访问 hasErrors 方法中的字段 providers 以显示错误消息.

    Within the <ul> I receive for each error providers[].url as e.fieldName. I thought it would be having some indices like providers[0].url etc. So my question is, how can I access the field providers within the hasErrors method properly to display the error messages.

    编辑

    控制器:

    @RequestMapping(value = "/saveDetails", method = RequestMethod.POST)
    public String saveDetails(@Valid @ModelAttribute("selectedProduct") final Product selectedProduct,
                              final BindingResult bindingResult, SessionStatus status) {
        if (bindingResult.hasErrors()) {
            return "templates/details";
        }
        status.setComplete();
        return "/templates/overview";
    }
    

    推荐答案

    您无法使用索引从 Set 中获取项目,因为集合没有顺序.Set 接口不提供基于索引获取项目的方法,因此对 Set 执行 .get(index) 会给你编译错误.使用 List 代替.这样,您就可以使用对象的索引访问对象.

    You cannot get an item from a Set using their index because sets don't have ordering. Set interface doesn't provide a method of getting an item based on index, so doing .get(index) to a Set will give you compile error. Use List instead. This way, you can access the objects using their index.

    所以改变Set提供者到:

    @Valid
    List<Provider> providers;
    

    不要忘记 @Valid 注释,以便它会向下级联到子对象.

    Don't forget the @Valid annotation so that it will cascade down to the child objects.

    此外,如果 th:errors 在表单内,它应该指向支持该表单的对象的属性,使用选择表达式 (*{...})

    Also, if th:errors is inside a form, it should be pointing to a property of the object that backs that form, using Selection Expression (*{...})

    <span class="help-block" th:each="provider, status : ${selectedProduct.providers}" 
        th:if="${#fields.hasErrors('providers[__${status.index}__].url')}" 
        th:errors="*{providers[__${status.index}__].url}">Error Url
    </span>
    

    编辑

    我看到您希望共同访问错误,而不是遍历它们.在这种情况下,您可以创建自定义 JSR 303 验证器.请参阅以下有用的代码片段:

    EDIT

    I see that you want to access the errors collectively, instead of iterating through them. In that case, you can create your custom JSR 303 validator. See the following useful code fragments :

    使用

    @ProviderValid
    private List<Provider> providers;
    

    ProviderValid 注释

    //the ProviderValid annotation.
    @Target({ ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = ProviderValidator.class)
    @Documented
    public @interface ProviderValid {
        String message() default "One of the providers has invalid URL.";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    }
    

    ConstraintValidator

    public class ProviderValidator implements ConstraintValidator<ProviderValid, List<Provider>>{
    
        @Override
        public void initialize(ProviderValid annotation) { }
    
        @Override
        public boolean isValid(List<Provider> value, ConstraintValidatorContext context) {
    
            //...
            //validate your list of providers here
            //obviously, you should return true if it is valid, otherwise false.
            //...
    
            return false;
        }
    }
    

    执行这些操作后,如果 ProviderValidator#isValid 返回 false,只需执行 #fields,您就可以轻松获得在 @ProviderValid 注释中指定的默认消息.hasErrors('providers')

    After doing these, you can easily get the default message you specified in the @ProviderValid annotation if ProviderValidator#isValid returns false by simply doing #fields.hasErrors('providers')

    这篇关于用于显示列表错误的表单绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆