Home > OS >  Why cant i bind data to my v-model when passing data from parent to child component?
Why cant i bind data to my v-model when passing data from parent to child component?

Time:10-10

I would like to pass data from my parent to child component and bind data to a input field through v-model to display data from my api call in parent component. But it seems to be problem when binding to input field i get this error message: Unexpected mutation of "data" prop.eslintvue/no-mutating-props

Partent Component

<script lang="ts">
import { defineComponent,ref } from 'vue';
import axios from 'axios'
import ChildComponent from '../components/ChildComponent.vue';

export default defineComponent({
    Component: { ChildComponent },
    name: 'IndexPage',
    setup() {
        return {
            fixed: ref(false),
            data: []
        };
    },
    mounted() {
        this.getData();
    },
    methods: {
        getData() {
            axios.get('/api/Hotel/'   2).then((response) => {
                this.data = response.data;
                this.fixed = true,
                    console.log(this.data);
            });
        }
    },
    components: { ChildComponent }
});

</script>

Child Component

<template>
    <main>
        <q-card >
      <q-card-section>
        <div >Terms of Agreement</div>
        <div >
    <div  style="max-width: 300px">
      
    <div>
                <q-input filled v-model="data.message" label="Filled" />

    </div>

    </div>
  </div>
      </q-card-section>

      <q-separator />

      <q-separator />

      <q-card-actions align="right">
        <q-btn flat label="Decline" color="primary" v-close-popup />
        <q-btn flat label="Accept" color="primary" v-close-popup />
      </q-card-actions>
    </q-card>

    </main>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
    props:['data'],
    name: 'ChildComponent',
    setup() {
        return {
            text: ref(''),
        };
    },

});


</script>

I have tried this to make mounted methods in my child components like this:


    <div>
       <q-input filled v-model="dataIn.message" label="Filled" />

    </div>

export default defineComponent({
    props:['data'],
    name: 'ChildComponent',
    setup() {
        return {
            text: ref(''),
            dataIn:{}
        };
    },

    mounted(){
    this.dataIn = this.data
    },
});

It seems to work but not optimal, i lost my data when i refresh my page. Anyone have a soulution ?

CodePudding user response:

Props should be read readonly. Your dataIn approach needs a watcher that will update your dataIn whenever your data props change

optionsApi:

export default defineComponent({
props:['data'],
name: 'ChildComponent',
data() {
   text: '',
   data: this.dataIn,
}

watcher: {
   dataIn: (newValue,oldValue){
      this.data = newValue
   }
}

});

CodePudding user response:

It seems that you want to make change to your data on your child component, you have to make it two-way binding. You should change your child code like this ( you are using custom q-input in your component and the attributes may differ a little but it is the same concept) :

<q-input
        :value="value"
        v-bind="$attrs"        
        v-on="$listeners"
        @input="(v) => $emit('input', v)"
      />

and instead of using data prop you should change it to value :

  props: {
    value: {
      type: [String], // multiple type also defenition accepted
      default: "",
    },
}

then in your parent simply use child component like this :

<your-child-component v-model="someData" />

CodePudding user response:

If I understood you correctly, you need to emit event from child or to use computed property with getter/setter:

const { ref, onMounted, watch } = Vue
const app = Vue.createApp({
  setup() {
    const items = ref({})
    const getData = () => {
      items.value = ({id: 1, message: 'aaa'})
      /*axios.get('/api/Hotel/'   2).then((response) => {
        this.data = response.data;
        this.fixed = true,
            console.log(this.data);
      });*/
    }
    onMounted(async() => await getData())
    //            
  • Related