如何异步验证 Vuetify 文本字段?

Posted

技术标签:

【中文标题】如何异步验证 Vuetify 文本字段?【英文标题】:How to validate Vuetify text field asynchronously? 【发布时间】:2018-08-14 09:21:00 【问题描述】:

Vuetify 中的Text fields 具有rules 属性,它采用返回true 或错误字符串的函数数组。如何使它们异步,以便使用 XHR 在服务器端进行验证?

类似:

<v-text-field :rules="[v =>  axios.get('/check?value=' + val).then(() =>  return true ) ]">

【问题讨论】:

好吧,你不能。至少不使用标准:rules。它们只接受布尔值或字符串返回。 @acdcjunior 为什么不呢?他不是返回布尔值吗? @Michael 他不是。 v =&gt; axios.get('/check?value=' + val).then(() =&gt; return true ) v =&gt; something(); 相同,后者打开一个块并因此返回 undefined。即使是(注意添加的return):v =&gt; return axios.get('/check?value=' + val).then(() =&gt; return true ) 它返回Promise&lt;boolean&gt;,而不是boolean 【参考方案1】:

一种解决方案是设置error-messages 属性:

&lt;v-text-field v-model="input" :error-messages="errors"&gt;

并使用watch 选项:

new Vue(
  data () 
    return 
      input: '',
      errors: []
    
  ,
  watch: 
    input (val) 
        axios.get('/check?value=' + val).then(valid => 
          this.errors = valid ? [] : ['async error']
        )
    
  
);

【讨论】:

为了避免副作用更喜欢在手表async input(val) this.errors = ['Vérification du code en cours ...']; const res = await axios.get('/check?value=' + val); // If value has been changed since start of function quit because result of last launched win if (val !== this.input) return if (res.data.valid) this.errors = []; else this.errors = ['Async error']; 【参考方案2】:

我必须进行后端验证以检查输入的用户名是否已经存在。我使用带有 JSON open API v3 的 swagger 客户端库来调用检查用户名值的方法。

所以我就这样解决了……

在我的 login.js 文件中,我定义了一个包含错误消息的字符串属性:

import swaggerClient from "../remote-client";
const strict = true;
const state = 
  hasError: false,
  error: null,
  usernameAlredyExists: ""
;
const getters = 
  hasError: state => state.hasError,
  error: state => state.error,
  usernameAlredyExists: state => state.usernameAlredyExists
;
const mutations = 
  checkingUsername(state) 
    state.hasError = false;
    state.error = null;
    state.usernameAlredyExists = "";
  ,
  usernameCheckedKO(state) 
    state.usernameAlredyExists = "Username already exists";
  ,
  usernameCheckedOK(state) 
    state.usernameAlredyExists = "";
  ,
  errorCheckingUsername(state, error) 
    state.hasError = true;
    state.error = error;
  ,
;
const actions = 
  userLogin( commit ,  username, password ) 
    // not relevant code
  ,
  checkUsername( commit ,  username ) 
    commit("checkingUsername");
    swaggerClient.userSwaggerClient
      .then(
        function(client) 
          return client.apis.UserHealthFacility.getHfUserUsernameWithUsername(
             username: username ,
            ,
            
          );
        ,
        function(reason) 
          // failed to load the JSON specification
          commit("errorCheckingUsername", reason);
        
      )
      .then(
        function(callResult) 
          if (callResult.body) 
            commit("usernameCheckedKO");
           else 
            commit("usernameCheckedOK");
          
        ,
        function(reason) 
          // failed to call the API method
          commit("errorCheckingUsername", reason);
        
      );
  
;

export default 
  namespaced: true,
  strict,
  state,
  getters,
  mutations,
  actions
;

然后在 Login.vue 文件中我有这段代码:

<v-card-text>
  <v-form ref="loginForm" v-model="loginValid" lazy-validation>
    <v-text-field
      v-model="username"
      label="Username"
      :rules="[rules.required]"
      :error-messages="usernameAlredyExists"
      v-on:change="callCheckUsername"
    ></v-text-field>
    <v-text-field
      v-model="password"
      :label="Password"
      :append-icon="showPassword ? 'visibility_off' : 'visibility'"
      :type="showPassword ? 'text' : 'password'"
      :rules="[rules.required, rules.minLength]"
      counter
      @click:append="showPassword = !showPassword"
    ></v-text-field>
  </v-form>
</v-card-text>
<v-card-actions>
  <v-spacer></v-spacer>
  <v-btn
    :disabled="!loginValid"
    @click="callUserLogin"
    color="primary"
    round
  >Login</v-btn>
</v-card-actions>

<script>
export default 
  data() 
    return 
      username: "",
      password: "",
      showPassword: false,
      loginValid: true,
      rules: 
        required: value => !!value || "Questo campo è obbligatorio",
        minLength: value =>
          value.length >= 8 || "Questo campo deve contenere almeno 8 caratteri"
      
    ;
  ,
  computed: 
    usernameAlredyExists() 
      return this.$store.getters["login/usernameAlredyExists"];
    
  ,
  methods: 
    callUserLogin() 
      if (this.$refs.loginForm.validate()) 
        this.$store.dispatch("login/userLogin", 
          username: this.username,
          password: this.password
        );
      
    ,
    callCheckUsername(value) 
      if (value) 
        this.$store.dispatch("login/checkUsername", 
          username: this.username
        );
      
    
  
;
</script>

这样看来效果不错

【讨论】:

以上是关于如何异步验证 Vuetify 文本字段?的主要内容,如果未能解决你的问题,请参考以下文章

使用 vuetify 规则进行验证的时间

Vuetify - 如何在表单上标记文本左侧和文本字段右侧

如何使用 Vuetify 文本字段插槽?

如何将 SVG 图像添加到 vuetify 文本字段

如何在 Vuetify 文本字段中更改 type=date 的时间戳格式

Vuetify 文本字段标签对齐