Em Ji Madhu
Em Ji Madhu

Reputation: 724

Mutation is not happening in custom component?

First of all, this is my current structure

CHILD COMPONENT

// HTML
<v-select
 v-bind:items="selectItems"
 v-model="selectedItemModel"
 label="Category"
 item-value="text"
></v-select>
<v-text-field
 label="Enter Value"
 type="number"
 v-model="compValModel"
></v-text-field>

// JS
props: {
 selectItems: {
  type: Array,
  required: true
 },
 selectedItem: {
  type: String
 },
 compVal: {
  type: Number
 },
}
date () {
 return {
  selectedItemModel: this.selectedItem,
  compValModel: this.compVal
 }
}

PARENT COMPONENT

// HTML

<component :selecItems="selectItems" :selectedItem="selectOneItem" 
:compVal="compOneVal"></component>

<component :selecItems="selectItems" :selectedItem="selectTwoItem" 
:compVal="compTwoVal"></component>

// JS
data () {
 return {
  selectItems: [some array]
 }
},
computed: {
 selectedOneItem: {
  get () {
    return this.$store.state.selectedOneItem
  },
  set (value) {
    this.$store.commit('selectedOneItem', value)
  }
 },
 selectedTwoItem: {
  get () {
    return this.$store.state.selectedTwoItem
  },
  set (value) {
    this.$store.commit('selectedTwoItem', value)
  }
 },
 compValOne: {
  get () {
    return this.$store.state.compValOne
  },
  set (value) {
    this.$store.commit('compValOne', value)
  }
 },
 compValTwo: {
  get () {
    return this.$store.state.compValTwo
  },
  set (value) {
    this.$store.commit('compValTwo', value)
  }
 }
}

Store

\\ STATE
compOneVal: 0,
compValTwo: 0,
selectedOneItem: null,
selectedTwoItem: null

\\ GETTER
compOneVal: (state) => state.compOneVal
compTwoVal: (state) => state.compTwoVal
selectedOneItem: (state) => state.selectedOneItem
selectedTwoItem: (state) => state.selectedTwoItem

\\ MUTATION
compOneVal (state, v) {
 state.compOneVal = v
},
compTwoVal (state, v) {
 state.compTwoVal = v
},
selectedOneItem (state, v) {
 state.selectedOneItem = v
},
selectedTwoItem (state, v) {
 state.selectedTwoItem = v
}

What's Working?

When i dont use component structure, and by placing the html explicitly in parent component. Everything is working perfectly.

What's Not Working?

When i use component structure, the mutation of all inputs and selects is not happening. It only has the initial state value.

So what i am doing wrong here? why things work without component structure but not with component structure?

Upvotes: 0

Views: 90

Answers (2)

thanksd
thanksd

Reputation: 55634

You have a couple syntax errors:

  • you pass a selecItems prop in the child component's tag, it should be selectItems.
  • you have a date function in your child component which should be data

But the root issue is that you aren't modifying those computed properties on the parent component. You're simply passing them to the child component. If you want the variable to change in the parent's scope in response to some event from the child component, you'll need to emit an event for that from the child and listen to that event in the parent.

Usually, you would do that by using the v-model directive on the child component tag. This way, when emitting an input event from the child, the property on the parent would update automatically (without needing to explicitly listen for the @input event in the parent).

However, since you are apparently trying to bind two separate values to the child component (selectedItem and compVal), you should emit two separate events when either related data property on the child changes:

props: {
  selectItems: {
    type: Array,
    required: true
  },
  selectedItem: {
    type: String
  },
  compVal: {
    type: Number
  },
}
data() {
  return {
    selectedItemModel: this.selectedItem,
    compValModel: this.compVal
  }
},
watch: {
  selectedItemModel(value) {
    this.$emit('selectedItemInput', value);
  },
  compValModel(value) {
    this.$emit('compValInput', value);
  }
}

Then, listen to those event on the parent and update the respective properties:

<component 
  :selecItems="selectItems" 
  :selectedItem="selectOneItem" 
  :compVal="compOneVal"
  @selectedItemInput="selectOneItem = $event"
  @compValInput="compOneVal = $event"
></component>

So now, whenever the selectedItemModel or compValModel data properties of the child component change, the parent's respective properties will update, firing their respective computed property set methods, thus updating the store.

Upvotes: 1

Cassio Cabral
Cassio Cabral

Reputation: 2682

Besides the typo(selecItems instead of selectItems) mentioned by @thanksd

I will give you some tips that it's recommended by the docs that can help

  1. Use actions to trigger mutations, instead of committing directly.
  2. Your state should be initialized with the type you wish to have there, example: empty array, object or string
  3. If you are accessing the store value for the child component, do it directly(access the store in the child). Insteading of passing props, unless really needed, example: you may want to pass a different value than the one in the store or use that same value on the parent
  4. If you have getters, maybe using the mapGetters could be a better options. Along with that, mapActions. So you can use direct values from store in your component, without using this.$store all the time

Upvotes: 0

Related Questions