Home > front end >  Vue3 and Vue-Select: How to emit child data to parent when using taggable prop?
Vue3 and Vue-Select: How to emit child data to parent when using taggable prop?

Time:05-28

I am using the Vue-Select library with Vue3. My objective is to let the user choose tags from an options list and also be able to create new tags if the tags do not exist in the options list.

This works fine in a child component, but I am having trouble passing/emitting the data up to the parent component. I need the data in the parent because I am going to package it up for form processing later.

How can I successfully get the tags from the child component and into the parent component's formData.tags property?

The code and sandbox link:

components/PostEditorTags.vue:

<template>
  <v-select
    :create-option="(tag) => ({ label: tag, value: tag })"
    v-model="selected"
    :options="options"
    multiple
    taggable
    @input="$emit('input', selected)"
    placeholder="add a tag"
  ></v-select>
  <br />
  child component data:
  <pre>{{ selected }}</pre>
</template>

<script setup>
import { ref } from 'vue';
import vSelect from 'vue-select';
import 'vue-select/dist/vue-select.css';

defineEmits(['input']);

const options = [
  { value: 'one', label: 'One' },
  { value: 'two', label: 'Two' },
  { value: 'three', label: 'Three' },
  { value: 'four', label: 'Four' },
  { value: 'five', label: 'Five' },
  { value: 'six', label: 'Six' },
  { value: 'seven', label: 'Seven' },
  { value: 'eight', label: 'Eight' },
  { value: 'nine', label: 'Nine' },
  { value: 'ten', label: 'Ten' },
];

let selected = ref([]);
</script>

components/Parent.vue:

<template>
  <h1>Post Tags</h1>
  <PostEditorTags @input="setTagsArr" />
  <br />
  <br />
  parent component data:
  <pre>{{ formData.tags }}</pre>
</template>

<script setup>
import PostEditorTags from './PostEditorTags.vue';

const formData = {
  // title: '',
  // content: '',
  tags: null,
};

function setTagsArr(x) {
  formData.tags = x;
}
</script>

CodePudding user response:

Try with watcher instead of event

components/PostEditorTags.vue:

<template>
  <v-select
    :create-option="(tag) => ({ label: tag, value: tag })"
    v-model="selected"
    :options="options"
    multiple
    taggable
    placeholder="add a tag"
  ></v-select>
  <br />
  child component data:
  <pre>{{ selected }}</pre>
</template>

<script setup>
import { ref, defineEmits, watch } from 'vue';
import vSelect from 'vue-select';
import 'vue-select/dist/vue-select.css';

const options = [{ value: 'one', label: 'One' }, { value: 'two', label: 'Two' }, { value: 'three', label: 'Three' }, { value: 'four', label: 'Four' }, { value: 'five', label: 'Five' }, { value: 'six', label: 'Six' }, { value: 'seven', label: 'Seven' }, { value: 'eight', label: 'Eight' }, { value: 'nine', label: 'Nine' }, { value: 'ten', label: 'Ten' },];

let selected = ref([]);

watch(
  () => selected.value,
  (newValue, oldValue) => {
    act(newValue);
  }
);

const emit = defineEmits(['input'])
const act = (val) => emit('input', val);
</script>

Make your data reactive in components/Parent.vue:

<template>
  <h1>Post Tags</h1>
  <PostEditorTags @input="setTagsArr" />
  <br />
  <br />
  parent component data:
  <pre>{{ formData.tags }}</pre>
</template>

<script setup>
import { reactive } from 'vue'
import PostEditorTags from './PostEditorTags.vue';

const formData = reactive({
  // title: '',
  // content: '',
  tags: null,
});

function setTagsArr(x) {
  formData.tags = x;
}
</script>

your demo

  • Related