The better way to Validate the props in Vue
Tags: vue, javascript, typescript, webdev
Published: 2020-04-19 07:19:17


Well, Whenever we communicate with data, we need to validate the data in order to achieve the expected behavior and these apply to any type of communication that happens within the application and when it comes to communicating from Parent to Child using `props` is no exception.

Let's dig into props in detail to write better and predictable code.

* [Array syntax](#chapter-1)
* [Object syntax](#chapter-2)
* [Object syntax with custom validator](#chapter-3)

First, let's define the parent component which is responsible to pass the data to the child.

### Parent component<a name=parent-component"></a>

Parent component consists of the movies list which basically passes the list of the movies to the child component. For better understanding will pass static props to more focus on how to write props better.

```javascript

<MovieList name="Movie 1" image="assets/images/movie-1.png" rating="7.5" 
watchlist="true">

```

### Array syntax <a name="chapter-1"></a>

Using array syntax, props can be directly passed using the name of the props and that will be used to display the data in the template.

```javascript

export default {
  name: 'MovieList',
  props: ['name', 'image', 'rating', 'watchlist']
}

```

Basically, It can be helpful for prototyping of the app but for big and scalable this approach is not enough to make code more scalable and reliable. Below are lists of disadvantages of using this syntax.

#### Cons

+ No Type checking
+ No Information indicates on mandatory and optional props
+ No Default value
+ No Appropriate custom validator

Well, All the shortcomings discussed above will be handled in the below examples to make our code more predictable.

### Object syntax <a name="chapter-2"></a>

Alternate to Array syntax, props can also be defined with object syntax and this syntax can facilitate us to use three key properties with prop attributes which helps us to write better code.

1. `type` checks the data type of prop.
2. `required` indicates whether the prop is required or not.
3. `default` indicates the value of prop if the parent component failed to pass that prop.

```javascript

export default {
  name: "MovieList",
  props: {
    name: {
      type: String,
      required: true
    },
    rating: {
      type: [Number, String],
      required: false,
      default: 5
    },
    wishlist: {
      type: Boolean,
      default: false
    },
    image: {
      type: String,
      default: require("@/assets/default-poster.png")
    }
  }
};

```

Below are the things which we can notice from the above code. 

* Props are now supporting types. The list of available types includes some of the JavaScript data types & others are as below.
 
  * String
  * Number
  * Object
  * Array
  * Boolean
  * Date
  * Function
  * Symbol

* A prop can accept multiple data types as used in the `rating` prop.

* Required props can be easily identified. 

* The default value is used in a case where the parent failed to pass the prop.

* If default property is set, the required properties become true automatically hence even not writing would make sense. ( e.g. wishlist & image prop)

So, The prop with object syntax is much better than the array syntax as it overcomes a lot of cons that come with object syntax, which we discussed above. but still, there is a catch in code with the image prop.

Imagine, the Parent component somehow passed the image URL wrong.

```html
<Movie-List name="Movie with incorrect image path" image="../assets/default.png"/>
```

In order to handle such cases, `prop` with object syntax have another property called `validator` to validate the incoming prop and if our requirement for the prop doesn't match, it throws an error. Thus, it helps to write more reliable and scalable code. Let's go through the example below

### Object syntax with custom validator <a name="chapter-3"></a>

```javascript

export default {
  props: {
    image: {
      type: String,
      default: require("@/assets/default-poster.png"),
      validator: propValue => {
        const hasImagesDir = propValue.indexOf("@/assets/") > -1;
        const listOfAvailableExt = [".jpeg", ".jpg", ".png"];
        const isValidExt = listOfAvailableExt.some(ext =>
          propValue.endsWith(ext)
        );
        return hasImagesDir && isValidExt;
      }
    }
  }
}

```

Here, the `validator` function accepts a prop value and if the value passes the given validations, then the prop image is visible otherwise it will throw an error in the console as below.

```javascript
[Vue warn]: Invalid prop: custom validator check failed for prop "image".
```

Now, we can simply correct the path of the image which renders the correct image.

Here is the working [codesandbox](https://codesandbox.io/s/prop-validator-j5ss7)

{% codesandbox j5ss7 %}

> NOTE: The `props` are validated before the component instance is created, hence the instance properties such as `data`, `computed`, etc will not be available to use inside `default` or `validator` function.

I hope it helps to write better code.🤞

Feel free to post any questions 📝 on the comments below. I would be more than happy to answer them.