0

I am reproducing this code (Codepen):

<div id="app">
  <v-app id="inspire">
    <div class="text-xs-center">

      <v-dialog
        v-model="dialog"
        width="500"
      >
        <v-btn
          slot="activator"
          color="red lighten-2"
          dark
        >
          Click Me
        </v-btn>

        <v-card>
          <v-card-title
            class="headline grey lighten-2"
            primary-title
          >
            Privacy Policy
          </v-card-title>

          <v-card-text>
            Hello there Fisplay
          </v-card-text>

          <v-divider></v-divider>

          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn
              color="primary"
              flat
              @click="dialog = false"
            >
              I accept
            </v-btn>
          </v-card-actions>
        </v-card>

      </v-dialog>
    </div>
  </v-app>
</div>

The only difference between my real code and this one, is that I defined dialog in store/index.js (this in Nuxt.js) where I declared dialog an element of the state:

return new Vuex.Store({                                                                                                                                              
        state: {                                                                                                                          
            dialog: false,

And then, in my current component I import that $store.state.dialog flag:

<script>                                                                                                                                                                 
import { mapState } from 'vuex';                                                                                                                            

export default {                                                                                                                                                         
    computed: {                                                                                                                                                          
        ...mapState([                                                                                                                                                    
            'dialog'                                                                                                                                                     
        ]),      
}
</script>

Whenever I click on the button, I get this error message:

[Vue warn]: Computed property "dialog" was assigned to but it has no setter.

How to fix this? Any alternative?

Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130

2 Answers2

2

You need to use the Vuex mutation to update the state.

https://vuex.vuejs.org/guide/mutations.html


In your example,

Your click event should be handled in the methods @click="handleClick"

methods: {
  handleClick() {
    this.$store.commit('openDialog')
}

In your store.js

mutations: {
  openDialog(state) {
    state.dialog = true
  }
}
Ru Chern Chong
  • 3,692
  • 13
  • 33
  • 43
1

mapState will only create getters. You should define a mutation in your vuex store, which will be able to change the state.

Just add this to your store:

...
mutations: {
 SET_DIALOG_FLAG_FALSE (state) {
   state.dialog = false;
},
//optional if you do not want to call the mutation directly
//must important different is, that a mutation have to be synchronous while
//a action can be asynchronous
actions: {
 setDialogFalse (context) {
  context.commit('SET_DIALOG_FLAG_FALSE');
 }
}

If you want to work with mapMutations/mapAction in your component:

import { mapMutation, mapActions } from vuex;
...
//they are methods and not computed properties
methods: {
 ...mapMutations([
  'SET_DIALOG_FLAG_FALSE'
 ]),
 ...mapActions([
  'setDialogFalse'
 ])
}

Now in your v-btn you can call the action or mutation.

<v-btn
  color="primary"
  flat
  @click="this.setDialogFalse"> I accept </v-btn>
Jns
  • 3,189
  • 1
  • 18
  • 23