Doyoun
Doyoun

Reputation: 97

How could I get changed value from vuetify select by emitting in atomic design pattern?

I am trying to get the changed value of vuetify v-select by using $emit but it doesn't work. I divided components by applying atomic design pattern (atoms(child component and not to connect with the store), organisms(parent component)) and vuex stores. I think $emit data is OK but anything doesn't work after the process.

This is for a new application for management page with using vue, vuex, vuetify, atomic design connecting to API server.

Components

child component - in atoms folder

<template>
  <v-select
    :items="list"
    :label="label"
    v-model="selected"
    item-value="id"
    item-text="name"
    return-object
    @change="changeSelected"
  ></v-select>
</template>

<script>
export default {
  props: ["list", "label", "defaultSelected"],
  data() {
    return {
      selected: this.defaultSelected
    };
  },
  methods: {
    changeSelected(newValue) {
      console.log(newValue);    // display changed new data
      this.$emit("changeSelected", newValue);
    }
  }
};
</script>

parent component - in organisms folder

<template>
  <v-select-child
    :select-label="label"
    :select-list="list"
    :default-selected="selected"
    @change-selected="changeSelected"    // problem issue?
  >
  </v-select-child>
</template>
<script>
import { mapState } from "vuex";
export default {
  data() {
    ...
  },
  computed: {
    ...mapState({
      list: state => state.list
    })
  },
  methods: {
    changeSelected() {
      console.log("changeSelected");    // doesn't work
      this.$store.dispatch("setSelected", { payload: this.selected });
    }
  }
};
</script>

vuex stores

index.js

export default new Vuex.Store({
  modules: {
    xxx
  },
  state: {
    list: [
      {
        name: "aaaaa",
        id: "001"
      },
      {
        name: "bbbbb",
        id: "002"
      }
    ]
  },
  getters: {},
  mutations: {},
  actions: {}
});

xxx.js

export default {
    selected: { id: "001" }
  },

  getters: {
    //
  },

  mutations: {
    updateSelected(state, payload) {
      console.log("payload");    // doesn't work
      console.log(payload);
      state.selected = payload;
      console.log(state.selected);
    }
  },

  actions: {
    setSelected({ commit }, payload) {
      console.log("Action");    // doesn't work
      commit("updateSelected", payload);
    }
  }
};

It does not print any console log after changeSelected function.

Upvotes: 3

Views: 1870

Answers (3)

ittus
ittus

Reputation: 22403

In document

Unlike components and props, event names don’t provide any automatic case transformation. Instead, the name of an emitted event must exactly match the name used to listen to that event.

That means if you emit event like $emit('changeSelected'), then you need to use @changeSelected. @change-selected will not work.

 <v-select-child
    :select-label="label"
    :select-list="list"
    :default-selected="selected"
    @changeSelected="changeSelected" 
  >
</v-select-child>

Upvotes: 1

Kubilay Cakmak
Kubilay Cakmak

Reputation: 1

You can also use watch;

  <v-select
    :label="label"
    :items="list"
    v-model="selected"
    item-value="id"
    item-text="name"
  ></v-select>
</template>

...
watch:{
   selected(){
      this.$emit('changeValue', this.selected.id');
   }
}
...

and from parent;

<child @changeValue="id = $event" .. />

Upvotes: 0

Doyoun
Doyoun

Reputation: 97

I found a solution below:

child component

<template>
  <v-select
    :label="label"
    :items="list"
    v-model="selected"
    item-value="id"
    item-text="name"
    return-object
  ></v-select>
</template>

<script>
export default {
  props: ["list", "label", "defaultSelected"],
  computed: {
    selected: {
      get() {
        return this.defaultSelected;
      },
      set(newVal) {
        if (this.selected !== newVal) {
          this.$emit("changeSelected", newVal);
        }
      }
    }
  }
};
</script>

parent component

<template>
  <v-select-child
   :label="label"
   :list="list"
   :defaultSelected="selected"
   @changeSelected="changeSelected"  // fix the property using camelCase
  ></v-select-child>
</template>

<script>
import { mapState } from "vuex";
export default {
  data() {
    ...
  },
  computed: {
    ...mapState({
      list: state => state.list
    })
  },
  methods: {
    changeSelected(val) {   // val: changed object value
      this.$store.dispatch("setSelected", { id:val.id });
    }
  }
};
</script>

Upvotes: 1

Related Questions