Element: 暴露form的验证结果,同时增加form显示时立刻执行验证

Created on 26 Dec 2016  ·  16Comments  ·  Source: ElemeFE/element

现在验证结果都在form-itemvalidateState中,如果希望将页面上的提交按钮的disabled属性和表单验证结果关联,只能自行创建一个computed变量,遍历formfields属性。由于computed在viewmodel创建的时候会立即执行,所以外层控件并不能立刻获取$refs,又要创建一个watch,里面用$nextTick,整个过程非常麻烦。

另外也希望验证模式可以支持表单显示就立即执行。

大致代码

computed: {
    valid: function () {
            if(!this.setFormValid){
                return false;
            }
            let fields = this.$refs.form.fields;
            let result = true;
            _.each(fields, f=> {
               result = result && (f.validateState === 'success');
            });
            return result;
        },
}

Most helpful comment

+1,除了Form的验证状态,有时候还需要知道表单是否dirty/pristine/touched,比如修改用户的时候可以根据是否dirty来设置提交表单按钮是否disabled

All 16 comments

大概理解你的意思,会考虑在 Form 对象里再暴露一个验证状态的字段

@baiyaaaaa 感谢,不过后来我想想这个问题的根源应该是默认的验证组件是异步的,然而我需要一个同步的状态,感觉这里本身存在不可调和的问题

觉得提交按钮不disable暂时也能接受。。现在就先watch吧orz

其实提交按钮根据验证规则来设置disabled挺不友好的

@baiyaaaaa 但是我觉得在引导步骤的时候就蛮有用的,比如注册的时候,下一步,下一步

@baiyaaaaa 目前这个验证框架还遇到几个问题

  1. 不知道要怎么注册一个自己的验证规则,比如内置了 email 的验证,我想加一个 phone 的验证,不知道从哪儿下手
  2. 这整个框架都是基于dom事件来驱动的,也就是说,但是一般用Vue处理表单是双向绑定的,这就意味着,某些情况下,几个字段相互依赖的验证会出现问题,比如A的required依赖与B有没有值,这个时候我们会把验证规则写在A字段里面,这个时候就出现一个问题,无论怎么修改B的值,只要没有触发A的change或者blur等事件,界面上永远不会出现错误提示,除非点提交,执行整个form验证,总感觉这个地方非常奇怪。

相比而言,是不是考虑用vue-validator这种框架会比这个更好呢

@languanghao 我觉得vue-validator的食用体验太差了。。。

异步和动态表单是难点,我整个人曾经都写懵了,最后靠计算属性自己来validate了。。

@reverland 我以前自己做的时候也是用computed来实现的,而且我觉得这种方案比较简单可靠

  1. 在el-form的created里面根据传入的form参数,为每个form字段动态创建computed属性,比如 fieldAValidate, fieldBValidate,computed函数里面就是执行对应该字段的验证方法

  2. 在el-form里创建一个computed属性valid,表示当前form的最终验证状态

  3. 对于async的验证,只要检测到验证规则是async的,默认就返回false,然后等验证完了callback

这种方法有几个好处

  1. 利用vue自动帮我们处理验证函数里面的依赖
  2. 再也不用关心dom的事件,反正都是值变化的时候执行

@languanghao 有时候会有动态表单的验证,creatd的时候不能确保有这些字段。

+1,除了Form的验证状态,有时候还需要知道表单是否dirty/pristine/touched,比如修改用户的时候可以根据是否dirty来设置提交表单按钮是否disabled

The translation of @tremblingBlue comment is this:
in addition to the Form validation status, and sometimes also need to know whether the form dirty / pristine / touched, such as when the user can be modified according to whether the dirty form to submit the form button is disabled.
I absolutely agree. I've been trying to mix in vee-validate for this purpose, but I can't seem to get it to attach to the el- components and have a single object of vee-validate fields. And of course its not great having two sources of validation going on.

@baiyaaaaa 有计划支持跟 vue-validator 一致的表单项状态(touched/untouched/pristine/dirty/modified)嘛?楼上 @tremblingBlue@dancampbell691 也有提到

@aNd1coder It's coming in next version

@baiyaaaaa 不知道 Form 对象里有暴露一个验证状态的字段了吗?没看到文档有写

As far as I've seen, and contrary to @baiyaaaaa 's comment on 7/24/17, the field states never came to be.
However, contrary to my own statement above on 5/18/17, I've been using Vee-Validate in conjunction with el-form's own validation with no issue for quite a while. I use vee-validate to track dirty/pristine/etc, and use the el-form validation for regular validation. Not ideal, but now that I have a pattern, it's barely an inconvenience.
As I recall, one of the keys to getting it to work was using the vee-validate configuration to change the default "Bag" names to something that was different than what el-form used:

const validateConfig = {
  errorBagName: 'veeErrors',
  fieldsBagName: 'veeFields',
  locale: 'en'
};
Vue.use(veeValidate, validateConfig);

Then in your el-form, you have a regular el-form-item with a el-whatever (input) that also has a v-validate attribute (and name):

            <el-form-item label="Vendor" prop="VendorId">
              <el-select 
                      name="Vendor" v-validate <!--both required for vee-validate-->
                      v-model="Main.VendorId">
                  <el-option v-for="vendor in vendors"
                          :key="vendor.Id"
                          :label="vendor.Name"
                          :value="vendor.Id">
                  </el-option>
              </el-select>
            </el-form-item>

Then you can make a Computed property for isFormDirty:

computed: {
    isFormDirty() {
        return Object.keys(this.veeFields).some(key => this.veeFields[key].dirty);
    }
    , //etc...
}

How is this closed issue when it was never solved, and its a pretty big deal breaker when dealing with forms 😞 ?
I'm not going to include a whole library (vee-validate) in my app bundle just so I can have a simple feature like this.

Was this page helpful?
0 / 5 - 0 ratings