0

I need to check whether my input field is empty or not.

Logic

  1. if form.name has value, use increase function
  2. if form.name is empty, use decrease function
  3. do not use increase, decrease functions on each character that user inputs or removes

Code

<el-form-item label="Product name *">
  <el-input v-model="form.name"></el-input>
</el-form-item>


methods: {
 increase() {
  this.percentage += 8.3;
  if (this.percentage > 100) {
    this.percentage = 100;
  }
 },
 decrease() {
  this.percentage -= 8.3;
  if (this.percentage < 0) {
    this.percentage = 0;
  }
 },
}

any idea?

Update

Script

data() {
    return {
        form: {
            name: '', // require
            slug: '',
            price: '', // require
            supplier_id: '', // require
            new_price: '',
            base_price: '',
            sku: '',
            qty: 1, // require
            active: '', // require
            photo: '',
            photos: [],
            shortDesc: '',
            longDesc: '',
            origin: '',
            tags: [],
            brand_id: '', // require
            categories: [],
            user_id: '',
            seoTitle: '',
            seoTags: '',
            seoPhoto: '',
            seoDescription: '',
            variations: [],
            options: [],
            condition: '', // require
            isbn: '',
            ean: '',
            upc: '',
            height: '',
            weight: '',
            lenght: '',
            width: '', // require
        },
    }
},
methods: {
    onSubmit(e) {
        e.preventDefault();
        axios.post('/api/admin/products/store', this.form)
        .then(res => {
            // do my things
        })
        .catch(function (error) {
            console.log('error', error);
        });
    },
}

HTML

<el-form ref="form" :model="form" label-width="120px" enctype="multipart/form-data">
    // my inputs (listed in form part in script above)

    <el-button type="primary" @click="onSubmit" native-type="submit">Create</el-button>
</el-form>

1 Answer 1

1

One possible solution would be to use @focus and @blur events to check if form.name has a value before increasing or decreasing, this would be fired on focus or on blur events, so you will not have the methods fired on each character input or deletion.

for example:

<el-form-item label="Product name *">
  <el-input @focus="checkName" @blur="checkName" v-model="form.name"></el-input>
</el-form-item>


methods: {

 checkName() {
   //If form.name has a value then run increase method, otherwise run decrease method
  !!this.form.name ? this.increase() : this.decrease()
 },
 increase() {
  this.percentage += 8.3;
  if (this.percentage > 100) {
    this.percentage = 100;
  }
 },
 decrease() {
  this.percentage -= 8.3;
  if (this.percentage < 0) {
    this.percentage = 0;
  }
 },
}

You can see a working fiddle HERE

UPDATE

Alright so i did follow the rules you state on your question, and i didn't know you wanted to get the percentage of completion of the form, so in order to do that, i would suggest to use a computed property, you can read more about computed properties in the VueJS Documentation, this way the percentage is calculated based on the criteria we can give it, and only if the form has values.

computed: {
        formProgress: function () {
        let totalInputs = Object.keys(this.form).length;
        let filledInputs = 0;
        Object.values(this.form).forEach(val => {
          if (!!val){
            filledInputs++;
          }
        });
        return (filledInputs/totalInputs)*100
        }
    },

As you can see in one single computed property you can handle the complex logic and return the value reactively, to explain it better, i'm counting the lenght of the form object, to get total number of inputs in your form, so it's important to have all your form data inside the form data object, then i convert that object to an array to iterate it, and i check if each property has a value on it, if does it, i add 1 to the filledInputs counter, and finally just return a simple math to get the percentage. please check the new Fiddle here to see it in action:

FORM PROGRESS FIDDLE

If you have any other doubt just let me know.

UPDATE 2:

All right in order to only count for specific inputs for the form progress, i have modified the code to work based on an array that contains the names of the properties that are required. here is the full code:

data() {
      return {
        form: {
            name: '',
          lastName: null,
          categories: [{}],
        },
        requiredFields: ['name', 'categories']
      };
    },
    computed: {
        formProgress: function () {
        let totalInputs = this.requiredFields.length;
        let filledInputs = 0;
        Object.entries(this.form).forEach(entry => {
            const [key, val] = entry;
          if (this.requiredFields.includes(key)){
            switch (val.constructor.name) {
                case "Array":
                if (val.length !== 0){
                    if (Object.keys(val[0]).length !== 0){
                    filledInputs++;
                    }
                }
                break
              case "Object":
                if (Object.keys(val).length !== 0){
                    filledInputs++;
                }
                break
              default:
                if (!!val){
                    filledInputs++;
                }
            }
          }
        });
        return Number((filledInputs/totalInputs)*100).toFixed(1)
        }
    },

And here is the updated FIDDLE

As you can see now i'm using Object.entries to get the key and value of the form object, so you can have a single form object to send to your backend, this way i'm checking first if the key is in the required fields, and if has a value, so all you need to do is update the requiredFields data array with the same names as your inputs data property to make the validation work, also there is a validation depending if is array, array of objects, or object, that way it will validate input on each data type.

Hope this works for you.

Sign up to request clarification or add additional context in comments.

11 Comments

hi, thanks for the answer but this increased the value each time i focus on input regardless of i placing value to that input or not. the idea behind this increase/decrease is to let user know how many percent of the form s/he has filled (probably you've seen such forms before)
@mafortis you didn’t say anything about what you wanted to accomplish with your question and I followed your rules, check my answer update, now it works for your requirements.
thank you so much, Ive just checked fiddle and it was working nicely, however the reason that i was trying to specific form inputs such as form.name was because i only need to do this math for my require inputs not all inputs in my form. let say my form has 20 inputs but only 3 of them are required, so this percentage 0 to 100 is only for those 3 inputs. is there a way to specity them in your code?
@mafortis you could simply have 2 form data objects, so you can compute only over the one that contains the required inputs, and other for the rest of inputs.
then i would have send 2 different type of data to process in backend right?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.