简体   繁体   中英

How can I pass v-model from a child component to parent component in vue?

I use vue version 2

My parent component like this:

<template>
  ...
      <page-heading
        :searchChange="searchChange"
      ></page-heading>

  ...
</template>

<script>
import PageHeading from "@/views/app/report/PageHeading";

export default {
  components: {
    "page-heading": PageHeading
  },
  methods: {
    searchChange(val) {
      console.log('test search')
      console.log(val)
      console.log(this.selectedDate)
    }
  }
};
</script>

My child component like this:

<template>
    ...
        <b-form-group>
            <Datepicker
            range
            v-model="selectedDate"
        />
        </b-form-group>
        <b-button type="submit" @click="searchChange(val)">Search</b-button>
    ...
</template>
<script>
import 'vue-datepicker-ui/lib/vuedatepickerui.css';
import VueDatepickerUi from 'vue-datepicker-ui';

export default {
  components: {
    Datepicker: VueDatepickerUi
  },
  props: [
    "searchChange",
  ],
  data() {
    return {
      selectedDate: [
        new Date(),
        new Date(new Date().getTime() + 9 * 24 * 60 * 60 * 1000)]
    };
  },

};
</script>

When click search button, I want to get selectedDate from child component. So in the parent component, I can read the selectedDate

How do I do that?

Please help. Thanks

You could use the $emit method to the parent with selectedDate as value in child component:

<template>
    ...
        <b-form-group>
            <Datepicker
            range
            v-model="selectedDate"
        />
        </b-form-group>
        <b-button type="submit" @click="search">Search</b-button>
    ...
</template>
<script>
import 'vue-datepicker-ui/lib/vuedatepickerui.css';
import VueDatepickerUi from 'vue-datepicker-ui';

export default {
  components: {
    Datepicker: VueDatepickerUi
  },
  props: [
    "search",
  ],
  data() {
    return {
      selectedDate: [
        new Date(),
        new Date(new Date().getTime() + 9 * 24 * 60 * 60 * 1000)]
    };
  },
methods:{
  search(){

   this.$emit('on-search',this.selectedDate);
  }
}

};
</script>

in parent add a handler for the on-search event:

<template>
  ...
      <page-heading
        @on-search="search"
      ></page-heading>

  ...
</template>

<script>
import PageHeading from "@/views/app/report/PageHeading";

export default {
  components: {
    "page-heading": PageHeading
  },
  methods: {
    search(val) {
      console.log('test search')
      console.log(val)
   
    }
  }
};
</script>

or you could use two way binding as in this answer

If I understood right you want to pass data from child component to parent component.

To achieve that you can make use of Emit events

It works as follows

Parent Component

<template>
  ...
      <page-heading
        @some-event="someMethod"
      ></page-heading>

  ...
</template>

<script>
import PageHeading from "@/views/app/report/PageHeading";

export default {
  components: {
    "page-heading": PageHeading
  },
  methods: {
    someMethod(event) {
      console.log('test search',event) //In this event you should get the selected date. 
    }
  }
};
</script>

Child Component

<template>
    ...
        <b-form-group>
            <Datepicker
            range
            v-model="selectedDate"
        />
        </b-form-group>
        <b-button type="submit" @click="searchChange">Search</b-button>
    ...
</template>
<script>
import 'vue-datepicker-ui/lib/vuedatepickerui.css';
import VueDatepickerUi from 'vue-datepicker-ui';

export default {
  components: {
    Datepicker: VueDatepickerUi
  },
  data() {
    return {
      selectedDate: [
        new Date(),
        new Date(new Date().getTime() + 9 * 24 * 60 * 60 * 1000)]
    };
  },
 methods:{
   searchChange(){
     this.$emit("some-event",this.selectedDate); // emit event fired to parent component with selected Date
   }
 }
};
</script>

You emit event from child component and you check for event in parent component method, you can log event to see what you have got from child component.

When passing data from parent to child we make use of props but for other way around you can do it using emit events.

Hope this helps.

You might want to look into .sync . Here's an example:

 // child Vue.component('child', { template: '#child-tpl', props: ['term'], computed: { localTerm: { get() { return this.term }, set(val) { this.$emit('update:term', val) } } } }) // parent new Vue({ el: '#app', data: () => ({ term: '' }), watch: { term: (val) => console.log(val) } })
 <script src="https://unpkg.com/vue@2.7.10/dist/vue.min.js"></script> <div id="app"> <child:term.sync="term" /> </div> <template id="child-tpl"> <input v-model="localTerm" /> </template>

There are three points of interest:

  • .sync modifier . As explained in the linked docs, :foo.sync="foo" is shorthand for
    v-bind:foo="foo" @update:foo="(val) => { foo = val }"
  • computed getter/setter in child. It's a pattern designed to make prop s usable with v-bind . Normally Vue warns when you try to modify a prop because any update in parent will override your change. So we create a computed with getter and setter. The getter reads the prop. The setter emits the value for the parent. The parent then updates the local value, through the prop. This ensures dual binding. Any change in child is reflected in parent and any change in parent is reflected in child.
  • since now you have the change in parent, you can watch it or derive new values from it, using computed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM