Search code examples
laravellaravel-5.3vuejs2vue-component

Is it possible to change props value from method in Vue component?


I have a component and i am passing value 543 to props :prop-room-selected,

<navigation-form :prop-room-selected='543'>
</navigation-form>

Now, From a button click, i am calling the function updateCoachStatus to change the value of propRoomSelected, but the props value is not updating.

{
    template: '#navigation-form',
    props: ['propRoomSelected'],
    data: function () {
      return {
        roomSelected: this.propRoomSelected,
      }
  },
  methods:{
      updateCoachStatus: function(event){
         this.propRoomSelected = 67;
      }
  }
}

I dont know how to change the value of props from function. Is it possible in Vue to update the value of props??


Solution

  • What you are doing will throw a warning in Vue (in the console).

    [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "propRoomSelected"

    The value will actually change inside the component, but not outside the component. The value of a parent property cannot be changed inside a component, and, in fact, the updated value will be lost if the parent re-renders for any reason.

    To update the parent property, what you should do is $emit the updated value and listen for the change in the parent.

    Vue.component("navigation-form",{
        template: '#navigation-form',
        props: ['propRoomSelected'],
        data: function () {
          return {
            roomSelected: this.propRoomSelected,
          }
      },
      methods:{
          updateCoachStatus: function(event){
             this.$emit("update-room-selected", 67) ;
          }
      }
    })
    

    And in your parent template listen for the event

    <navigation-form :prop-room-selected='propRoomSelected'
                     @update-room-selected="onUpdatePropRoomSelected">
    </navigation-form>
    

    Here is an example.

    This is a common pattern and Vue implemented a directive to make it slightly easier called v-model. Here is a component that supports v-model that will do the same thing.

    Vue.component("navigation-form-two",{
        template: '#navigation-form-two',
        props: ['value'],
        data: function () {
          return {
            roomSelected: this.value,
          }
      },
      methods:{
          updateCoachStatus: function(event){
             this.$emit("input", 67) ;
          }
      }
    })
    

    And in the parent template

    <navigation-form-two v-model="secondRoomSelected">
    </navigation-form-two>
    

    Essentially, for your component to support v-model you should accept a value property and $emit the input event. The example linked above also shows that working.