akor
akor

Reputation: 193

How to apply individual error message in VueJs Element?

I have a form (http://element.eleme.io/#/en-US/component/form) in application, where I do server side validation. But I have not glu how to add error message for specific inputs.

Upvotes: 0

Views: 7873

Answers (4)

lokesh
lokesh

Reputation: 343

add a ref with any name and do the following:

In js do this
this.$refs.formData.errorBucket=[]
<v-text-field                                                                  
  ref="formData"
  :rules="[rules.required, rules.max]">
</v-text-field>

Upvotes: 0

Njogu Amos
Njogu Amos

Reputation: 11

I figured out a Laravel solution based on Laracast project. The advantage of this approach is that the Error class is reusable.

In your component.vue,

  • Bind individual input error with errors.get('field') e.g :error="errors.get('email')"
  • Import Error class (see snippet below)
  • Add errors object to vue data
  • Make axios request and record response data

<template>
  <el-form  label-position="top"
            label-width="100px"
            :model="loginForm"
            :rules="rules"
            @submit.prevent="validateForm"
            ref="loginForm"
            status-icon validate-on-rule-change>

    <el-form-item label="email" prop="email" :error="errors.get('email')">
      <el-input   v-model="loginForm.email" placeholder="Enter your email"></el-input>
    </el-form-item>

    <el-form-item label="password" prop="password" :error="errors.get('password')">
      <el-input   v-model="loginForm.password" placeholder="Enter your password"></el-input>
    </el-form-item>

    <!-- Note about get() method in :error="errors.get('password')" see errors js -->

  </el-form>
</template>

<script>
  import { Errors } from './../templates/errors.js';
  export default {

    // Data
    data() {
      return {
        loginForm: {
          email: '',
          password: '',
        },

        // This is where we manage laravel errors
        errors: new Errors(),

        // Local validation disabled
        rules: {
          email: [
            { required: false, message: 'Please enter your email', trigger: 'blur' },
            // required set to false to for the sake of testing with laravel
          ],
          password: [
            { required: false, message: 'Please enter your password', trigger: 'blur' },
            // required set to false to for the sake of testing with laravel
          ],
        }
      };
    },

    // Methods
    methods: {

        // Validate form data
        submitForm(loginForm) {

// Clear Laravel errors before submitting form
this.errors.clear()

          this.$refs[loginForm].validate((valid) => {
            if (valid && ! this.errors.any()) {
              console.log('Data is validated. Submitting' + this.loginForm);
              this.login()
this.$refs[loginForm].validate()

            } else {
              console.log('Cannot submit, Invalid data');
              return false;
            }
          });
        },

        // post data
        login(){
          axios.post('/login'.login, this.loginForm).then( response => {
            // Data submitted successifully
          })
          .catch(error => {
            // There was an error like
            this.errors.record(error.response.data.errors)
            // Note: see errors.js for record method
          });
        }

    }
  }
</script>

Then import errors.js (credit Laracast project)

export class Errors {
    /**
     * Create a new Errors instance.
     */
    constructor() {
        this.errors = {};
    }


    /**
     * Determine if an errors exists for the given field.
     *
     * @param {string} field
     */
    has(field) {
        return this.errors.hasOwnProperty(field);
    }


    /**
     * Determine if we have any errors.
     */
    any() {
        return Object.keys(this.errors).length > 0;
    }


    /**
     * Retrieve the error message for a field.
     *
     * @param {string} field
     */
    get(field) {
        if (this.errors[field]) {
            return this.errors[field][0];
        }
    }

    /**
     * Retrieve flash message if any
     *
     * @param {string} field
     */
    getFlash(field) {
        if (this.errors[field]) {
            return this.errors[field];
        }
    }


    /**
     * Record the new errors.
     *
     * @param {object} errors
     */
    record(errors) {
        this.errors = errors;
    }


    /**
     * Clear one or all error fields.
     *
     * @param {string|null} field
     */
    clear(field) {
        if (field) {
            if (this.has(field)) {
                delete this.errors[field];
            }

            return;
        }

        this.errors = {};
    }
}

Upvotes: 0

parker_codes
parker_codes

Reputation: 3397

Each el-form-item needs a prop attribute for the frontend validation to work. They also need a bound error attribute. I just made each the same as the field name for simplicity, like so:

<el-form-item label="Email" prop="email" :error="errors.email">
    <el-input v-model="form.email" type="email"></el-input>
</el-form-item>

Then when the form is submitted I run my validator for the frontend rules (using Element's rules). Right after that I use axios to post to the server (Laravel). I loop through any errors, and update the value in the errors object. Whenever the form is submitted, I clear the errors (if you don't clear them, the errors will not show up on consecutive form submissions).

data() {

    let passwordsMatch = (rule, value, callback) => {
        if ( value != this.form.password )
            return callback(new Error('Passwords do not match'));

        return callback();
    };

    let form = {
        first_name: '',
        last_name: '',
        email: '',
        phone: '',
        password: '',
        password_confirmation: '',
    };

    // copy blank values, not reference
    let errors = {...form};
    let blankErrors = {...form};

    return {

        form,

        errors,

        blankErrors,

        rules: {
            first_name: [
                { required: true, message: 'First Name is required', trigger: 'blur' },
            ],
            last_name: [
                { required: true, message: 'Last Name is required', trigger: 'blur' },
            ],
            email: [
                { required: true, message: 'Email is required', trigger: 'blur' },
                { type: 'email', message: 'Must be an email', trigger: 'blur' },
            ],
            phone: [
                { required: true, message: 'Cell Phone is required', trigger: 'blur' },
                // TODO: finish phone validation
                //{ type: 'number', message: 'Must be a phone number', trigger: 'blur' },
            ],
            password: [
                { required: true, message: 'Password is required', trigger: 'blur' },
            ],
            password_confirmation: [
                { required: true, message: 'Password is required', trigger: 'blur' },
                { validator: passwordsMatch, trigger: 'blur' },
            ],
        },
    }
},

methods: {

    createAccount() {

        this.clearErrors();


        let passed = this.runValidator();

        if (! passed) return;


        axios.post(`/register`, this.form)
            .then(response => {

                EventBus.$emit('user-form-completed', this.form);

                return;

            })
            .catch(error => {

                const errors = error.response.data.errors;

                for (let index in errors) {

                    let error = errors[index][0];

                    this.errors[index] = error;
                }
            });
    },


    clearErrors() {
        this.errors = {...this.blankErrors};
    },


    runValidator() {

        let passed = false;

        this.$refs.form.validate((valid) => {
            if (valid) passed = true;
        });

        return passed;
    },
},

Upvotes: 1

Niklesh Raut
Niklesh Raut

Reputation: 34914

I am using Laravel and I usually do like this, My validation in Laravel controller

    return Validator::make($data, [
        'email' => 'required|email',
        'password' => 'required|min:6',
    ]);

My vue.js code in if error comes

if(error.response.status == 400){
    let errors = error.response.data.errors;
    for(let i in errors){
        document.querySelector("div[for='"+i+"']").innerHTML = errors[i][0];
    }
}else if(error.response.status == 401){
    console.log(error.response);
    let errors = error.response.data;
    document.querySelector("div[for='password']").innerHTML = errors;
}

Complete vue component is

const Login = { 
template: `
    <div class="container">
      <div class="row row-body"> 
        <div class="col-12 col-md-6 offset-md-3">
          <div class="row">
            <div class="col-12 col-md-12 text-center">
              <h1>Login</h1>
            </div>
          </div>
          <div class="row">
            <div class="col-12 col-md-12">
              <form method="POST" action="">

                <div class="row pt-3 pb-3">
                  <div class="col-12 col-md-10 offset-md-1 form-group">
                    <input class="form-control form-rounded" placeholder="Email*" v-model="email">
                    <div for="email" class="text-danger"></div>
                  </div>
                </div>
                <div class="row pb-3">
                  <div class="col-12 col-md-10 offset-md-1 form-group">
                    <input class="form-control" placeholder="Password*" v-model="password" type="password">
                    <div for="password" class="text-danger"></div>
                  </div>
                </div>
                <div class="row pt-3">
                  <div class="col-12 col-md-12 form-group text-center">
                    <button @click="login" class="btn as-btn-outline as-btn-dark mx-2 my-2 my-sm-0 big-btn" type="button">LOGIN</button>
                  </div>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
`,
data(){
    return {
        email: '',
        password: ''
    }
},
mounted(){
    /**/
},
methods:{
        login: function(){
            var formdata = {};
            formdata.email = this.email;
            formdata.password = this.password;
            axios
                  .post('http://far.test/api/login',formdata)
                  .then(response => {
                    console.log(response.data);
                    if(response.data.token !== undefined){
                        this.$parent.is_auth = true;
                        sessionStorage.setItem('asset_token', response.data.token);
                        router.push({ path: '/home' });
                    }
                  })
                  .catch(error => {
                    if(error.response.status == 400){
                        let errors = error.response.data.errors;
                        for(let i in errors){
                            document.querySelector("div[for='"+i+"']").innerHTML = errors[i][0];
                        }
                    }else if(error.response.status == 401){
                        console.log(error.response);
                        let errors = error.response.data;
                        document.querySelector("div[for='password']").innerHTML = errors;
                    }

                  })
                  .finally(() => console.log('finally')/*this.loading = false*/);

        },
    }
}

And related laravel controller methods are

public function validateAuditLogin($data){
     return Validator::make($data, [
        'email' => 'required|email',
        'password' => 'required|min:6',
    ]);
}

public function loginForAudit(Request $request){
    $requestAll = $request->all();
    $pwd = base64_decode($requestAll["password"]);
    for($i=0;$i<4;$i++){
        $pwd = base64_decode($pwd);
    }
    $requestAll['password'] = $pwd;
    $validator =  $this->validateAuditLogin($requestAll);
    if($validator->fails()){
        return response()->json(['errors'=>$validator->messages()],400);
    }
    if ($user = \Auth::attempt(['email' => $requestAll['email'], 'password' => $requestAll['password'] ])) {
        $token = str_random(40);
        User::where('id',\Auth::id())->update(['api_token'=>$token]);
        return response()->json(['token'=>$token]);
    }else{
        return response()->json('Email or password is incorrect',401);
    }
}

Upvotes: 0

Related Questions