skip to Main Content

The parent component has data that I want to pass to the child component. For example, I created such a component with data.
Parent component

<template>
         
   <NameUser :data="userData"></NameUser>
   <div>first name: {{ userData.firstName }}</div>
   <div>last name: {{ userData.lastName }}</div>
 
</template>

<script setup>
    
    import {ref} from 'vue'
    import NameUser from '../components/NameUser.vue';
    const userData = ref({
        firstName: 'testName',
        lastName: 'testLastName'
    })

</script>

In the child component, I receive this data and will have to pass it back to the parent component after changing it.
Child component

<template>

    <label>First name</label>
    <input :value="data.firstName" @input="changeData">

    <label>Last name</label>
    <input :value="data.lastName" @input="changeData">

</template>

<script setup>

    const props = defineProps({
        data:Object
    })

    function changeData(){}

</script>

Help to implement the changeData function. Please tell me if it is necessary to use the computed property to avoid re-rendering.

2

Answers


  1. The nicest way I could come up with doing this is as follows

    here is a codesdandbox.io working version of the code below


    Parent.vue

    <script setup>
    import { ref } from "vue";
    import NameUser from "./NameUser.vue";
    const userData = ref({
      firstName: "testName",
      lastName: "testLastName",
    });
    </script>
    
    <template>
      <name-user v-model="userData"></name-user>
      <div>first name: {{ userData.firstName }}</div>
      <div>last name: {{ userData.lastName }}</div>
    </template>
    

    NameUser.vue

    <script setup>
    import { ref, watch } from "vue";
    const props = defineProps(["modelValue"]);
    const firstName = ref(props.modelValue.firstName);
    const lastName = ref(props.modelValue.lastName);
    const emit = defineEmits(["update:modelValue"]);
    watch([firstName, lastName], () =>
      emit("update:modelValue", { firstName, lastName }),
    );
    </script>
    
    <template>
      <label>First name</label>
      <input v-model="firstName" />
    
      <label>Last name</label>
      <input v-model="lastName" />
    </template>
    
    Login or Signup to reply.
  2. SFC Playground

    You can use a separate reactive object inside NameUser to update it from inputs and synchronize it with a model value. That way you can add any additional inputs without declaring any extra variables.

    Also your changeData doesn’t receive any extra parameter to distinguish different props in the user object. Use v-model on inputs instead. Otherwise it’s unnecessarily complicated.

    NameUser.vue

    <script setup>
    
        import {reactive, watch} from 'vue';
        const props = defineProps({
            modelValue: Object
        });
    
        const value = reactive({});
        const emit = defineEmits(['update:modelValue']);
        
        // 2-way binding - watch for the prop changes
        watch(() => props.modelValue, data => Object.assign(value, data), {immediate:true});
        // create a copy of value so the above watch would be triggered
        watch(value, value => emit('update:modelValue', {...value}));
    
    </script>
    <template>
    
        <label>First name</label>
        <input v-model="value.firstName" >
    
        <label>Last name</label>
        <input v-model="value.lastName" >
    
    </template>
    

    Parent.vue:

    <script setup>
        
        import {ref} from 'vue'
        import NameUser from './NameUser.vue';
        const userData = ref({
            firstName: 'testName',
            lastName: 'testLastName'
        })
    
    </script>
    
    <template>
    
       <NameUser v-model="userData"></NameUser>
       <div>first name: {{ userData.firstName }}</div>
       <div>last name: {{ userData.lastName }}</div>
    
        <br/>
       <div>Check 2-way binding:</div>
       <NameUser v-model="userData"></NameUser>
     
    </template>
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search