Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the data from a child component in Vue3?

Im newbie in web development, and also in vue. My idea is to make a component that has some user input, like text, a selection from a combobox and a checkbox. This component should be genereted dinamically by the user, I mean, the user needs to be able to add more and more of this components in the web via the "+" button on the parent component:

// Child component
<template>
    <div class="row">
        <p>Key:</p>
        <input type="text" v-model.trim="key">
        <p>Type:</p>
        <select name="type" v-model="type">
            <option value="Integer">Integer</option>
            <option value="String">String</option>
            <option value="List">List</option>
        </select>
        <p>Required:</p>
        <input type="checkbox" name="required" v-model="required">
        <button>More options</button>
    </div>
</template>

<script setup>
import { ref } from 'vue';

const key = ref('key');
const type = ref('Integer');
const required = ref(true);

defineExpose({
    'key':key,
    'type':type,
    'required':required
})

</script>

<style scoped>
.row {
    display: flex;
}
p{
    padding: 20px;
}
</style>
// ParentComponent
<template>
      <div>
        <div v-for="(item, index) in items" :key="index">
          <Row :is="item"/>
        </div>
        <button @click="addComponent">+</button>
        <button @click="logComponentsData"></button>
      </div>
</template>
    
<script setup>
import { ref } from 'vue';
import Row from './Row.vue';

const items = ref([]);

const addComponent = () => {
  items.value.push({});
};

</script>

I used refs and v-model and also a sort of rendering list that im not sure if it is correctly applied.

In the web I can se through the vue extension that the data is changing in my child components: website img

But I dont know how is the right or any way possible for me to log all the child components data (key, type, required) for later usage.

I may want to store that data on local storage later on.

Any help would be much appreciated!

like image 747
Ignacio Sambrailo Avatar asked Oct 25 '25 07:10

Ignacio Sambrailo


1 Answers

Vue SFC Playground

Use v-model for the child component:

// ParentComponent
<template>
<div>{{items}}</div>
      <div>
        <div v-for="(_, index) in items" :key="index">
          <ChildComponent v-model="items[index]"/>
        </div>
        <button @click="addComponent">+</button>
      </div>
</template>
    
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const items = ref([]);

const addComponent = () => {
  items.value.push({key:'key', type:'Integer', required:true});
};

</script>

ChildComponent.vue

// Child component
<template>
    <div class="row">
        <p>Key:</p>
        <input type="text" v-model.trim="value.key">
        <p>Type:</p>
        <select name="type" v-model="value.type">
            <option value="Integer">Integer</option>
            <option value="String">String</option>
            <option value="List">List</option>
        </select>
        <p>Required:</p>
        <input type="checkbox" name="required" v-model="value.required">
        <button>More options</button>
    </div>
</template>

<script setup>

import {computed} from 'vue';

const props = defineProps({'modelValue':{type: Object, required:true}});
const emit = defineEmits(['update:modelValue']);

const value = computed({
  get(){ return props.modelValue; },
  set(val){ emit('update:modelValue', value.value); }
});

</script>

<style scoped>
.row {
    display: flex;
}
p{
    padding: 20px;
}
</style>
like image 74
Alexander Nenashev Avatar answered Oct 27 '25 00:10

Alexander Nenashev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!