w3resource

Props in Vue.js: Types, Validation, and Best Practices

The tutorial on component basics is a perquisite for this tutorial.

Prop Casing (camelCase vs kebab-case)

Browsers interpret uppercase characters as lowercase, this is because HTML attribute names are case-insensitive. Thus when we used in -DOM templates, camelCased props names need to use their equivalent kebab-case:

JS

Vue.component('blog-post', {
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})

HTML

<blog-post post-title="hello!"></blog-post>

However, this limitation does not apply when using string templates.

rop Types

Thus far, we have seen props listed as an array of strings only:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

However, we would want every prop to be of a specific type. In such cases, we can list props as an object, where the properties' values and name contain the property types and name:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

This will document your component as well as warn the users in the browser javascript console when they pass the wrong type.

Passing Static or Dynamic Props

Thus far, we have both seen props passed a static value as in this case:

<blog-post title="My journey with Vue"></blog-post>

And also seen dynamically assigned props with v-bind, as in this case:

<!-This will dynamically assign the value of a variable -->
<blog-post v-bind:title="post.title"</blog-post>

Passing a Number

<!-- Though `42` is static, using v-bind will tell Vue that -->
<!-that this is a JavaScript expression and not a string. -->
<blog-post v-bind:likes="42"></blog-post>```

<!-Assign a value to the variable dynamically -->
<blog-post v-bind:likes="post.likes"></blog-post>

Passing a Boolean

<!-when we include the prop with no value this will imply `true`. -->
<blog-post is-published></blog-post>

<!-- Though `false` is static, we need to use v-bind to tell Vue that -->
<!-- this is a JavaScript expression and not a string.          -->
<blog-post v-bind:is-published="false"></blog-post>

<!-this will dynamically assign to the value of a variable. -->
<blog-post v-bind:is-published="post.isPublished"></blog-post>

Passing an Array

<!-The v-bind directive tells vue that this is an array and not a string-->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>

<!-Here we assign the variable to a value dynamically. -->
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>

Passing an Object

<!-The v-bind directive tells vue that the static object is a JavaScript expression and not a string -->
```<blog-post
  v-bind:author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
></blog-post>```

<!-Dynamic assigning a value to a variable -->
<blog-post v-bind:author="post.author"></blog-post>

Passing the Properties of an Object

When we want to pass all the properties of an object as props, we can use v-bind without an argument (v-bind instead of v-bind:prop-name). For instance,consider a post object:

post: {
  id: 1,
  title: 'My Journey with Vue.Js'
}

With the following template:

<blog-post v-bind="post"></blog-post>

This will be equivalent to:

<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

One-way Data Flow

By default, data only flows from the parent component to the child component. This helps to prevent accidental mutation of parent state (this is good for your application)

However you might be tempted to mutate a prop in this two cases:

  1. The prop was used to pass an initial value which the child component wants to use as a local data property afterwards. In such a case, it is most preferable to define a local data property that uses the prop as its initial value.
  2. we need to transform a prop that was passed in as a raw-value.

Prop Validation

Prop validation is very important when the components we are developing is to be used ny others. When we want to specify props validation, we can provide to the value of the props an object with validation requirements. Instead of providing an array of srings.

Vue.component('my-component', {
  props: {
    // A Basic type check (`null` and `undefined` values will pass any of the type validation)
    propA: Number,
    // A Multiple possible types
    propB: [String, Number],
    // A Required string
    propC: {
      type: String,
      required: true
    },
    // A Number with a default value
    propD: {
      type: Number,
      default: 100
    },
    // An Object with a default value
    propE: {
      type: Object,
      // An Object or array defaults must be returned from a factory function
      default: function () {
        return { message: 'hello' }
      }
    },
    // A Custom validator function
    propF: {
      validator: function (value) {
        // to that the value must match one of these strings
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

A type can be one the following native constructors:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

It could also be a custom constructor function and the assertion would be made with an instanceof check:

function Person (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}```
Then you could now use:
```Vue.component('blog-post', {
  props: {
    actor: Person
  }
})

To validate that the value of the actor prop was created with new Person.

Non-prop Attributes

Non prop-attributes are attributes that are passed to a component, but does not have a corresponding prop defined.

This is very important when we are building third party libraries, because we don't know the full context which the components might be used.

For instance, consider using a 3rd-party bootstrap-date-input component with a [lugin which requires a data-date-picker attribute on the input.

We could add this attribute to our component instance:

<bootstrap-date-input data-date-picker="activated"></bootstrap-date-input>

Replacing/Merging with Existing Attributes

Given that the template for bootstrap-date-input is:

<input type="date" class="form-control">

When we need to specify a theme for the date picker plugin, we might need to add a specific class:

<bootstrap-date-input
  data-date-picker="activated"
  class="date-picker-theme-dark"
></bootstrap-date-input>

Disabling Attribute Inheritance

When we do not want the root element of a component to inherit attributes, we can set inheritAttrs:false in the component's option:

Vue.component('my-component', {
  inheritAttrs: false,
  // ...
})

when we combine inheritAttr and $attrs, we can manually decide which element we want to forward attributes to.

Previous: Vue.js Form Input Bindings: v-model for Two-Way Data Binding.
Next: Custom Events in Vue.js: Naming Conventions and Best Practices.



Become a Patron!

Follow us on Facebook and Twitter for latest update.

It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.

https://w3resource.com/vue/learn-vue-props.php