Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js prop validation for props

I have a child component with the following props declaration:

   props: {
        count: Number,
        maxNum: Number
   }

This is normally fine, but I also have maxNum mapped to an input field with:

<input type="text" v-model="maxNum" value="maxNum">

So even if the user puts "4" in the input, Vue.js thinks that it's a string, when in reality it's a valid number if parsed right.

I tried doing this, but it didn't fail properly on the input "apple":

   props: {
        maxNum: {
            validator: function (v) {
                parseInt(v);
                return true;
            }
        }
   }

What's the prescribed way of validating props when a v-model is involved?

like image 766
lollercoaster Avatar asked Mar 09 '23 06:03

lollercoaster


2 Answers

Ah, so Vue.JS actually provides a nice way to do this apparently.

<input type="text" v-model.number="maxNum" value="maxNum">

The .number modifier lets the v-bind:value part of the v-model equation to treat the input value as a number.

Reference on v-model.number in Vue.JS guide is here.

like image 54
lollercoaster Avatar answered Mar 19 '23 04:03

lollercoaster


I see you figured out how to solve your issue, but I'll still try to explain what went wrong here.

Issue 1

I'm guessing you expected parseInt to break on inputs without a number in them, but that's not the case. parseInt(null), parseInt('foo') and parseInt([{ bar: 'Baz' }]) will all work fine, they'll just return NaN. Consequently, your validator will always proceed to the second line and return true, thus treating any input as valid. To fix it, you would have to run parseInt on your input and check if it returns NaN, so your validator would like like this:

validator: function (v) {
    return !isNan(parseInt(v));
}

Issue 2

You're not really looking for a validator. A validator just checks input values and decides whether they are valid or not, it doesn't change them in any way. In other words, the corrected validator above wouldn't cast '13' to 13, it would just prevent input like 'apple' or undefined. '13' would get through unchanged and you would have to manually cast it later on.

The feature you are looking for was provided as an optional coerce function on each component prop in Vue 1, but it was removed for version 2. If you ever need to do it in a slightly more complicated manner that isn't covered by the solution you linked to, the officially recommended way is to simply use a computed value.

like image 39
mzgajner Avatar answered Mar 19 '23 03:03

mzgajner