/ Gists / v-model, Parent <-> Child 2 way databinding
On gists

v-model, Parent <-> Child 2 way databinding

Vue.js

1.vue Raw #

<!--Emit + props-->

<!--PARENT-->
<template>
  <div>
    <h1>A1 - parent</h1>
    <input
      :value="time"
      @input="time = $event.target.value"
      class="border border-gray-400"
    />
    <b1 @on-parent="this.time = $event" :time="time" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      time: null
    }
  },
  methods: {},
  computed: {},
  mounted() {}
}
</script>



<!--CHILD-->
<template>
  <div>
    <h1>B1 - child</h1>
    <input
      :value="time"
      @input="sendData($event.target.value)"
      class="border border-gray-400"
    />
  </div>
</template>

<script>
export default {
  emits: ['on-parent'],
  props: ['time'],
  data() {
    return {}
  },
  methods: {
    sendData(val) {
      this.$emit('on-parent', val)
    }
  },
  computed: {},
  mounted() {}
}
</script>

2.vue Raw #

<!--modelUpdate-->

<!--PARENT-->
<template>
  <div>
    <h1>A2 - parent</h1>
    <!-- toto je rozepsany model, lze pouzit a je to lepsi 
    <input v-model="inputValue" class="border border-gray-400" />
    -->
    <input
      :value="inputValue"
      @input="inputValue = $event.target.value"
      class="border border-gray-400"
    />
    <b2 v-model:propstochild="inputValue" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputValue: ''
    }
  },
  methods: {},
  computed: {},
  mounted() {}
}
</script>


<!--CHILD-->
<template>
  <div>
    <h1>B2 - child</h1>
    <input
      :value="propstochild"
      @input="$emit('update:propstochild', $event.target.value)"
      class="border border-gray-400"
    />
  </div>
</template>

<script>
export default {
  emits: ['update:propstochild'],
  props: ['propstochild'],
  data() {
    return {}
  },
  methods: {},
  computed: {},
  mounted() {}
}
</script>


testing.html Raw #

<h1 class="font-bold">VUE test</h1>
<hr class="my-3" />
<h2 class="font-medium">1) Emit + props</h2>
<hr class="my-3" />
<a1 />
<hr class="my-3" />
<h2 class="font-medium">2) ModelValue</h2>
<a2 />

3.vue Raw #

<!--Parent component-->
.
.
<region-map v-model="selectedFilterByDistrict" />
.
.


<script>
export default {
  props: ['list', 'listType', 'listService'],
  data() {
    return {
      selectedFilterByDistrict: null,
      selectedFilterByType: null,
      selectedFilterByService: null
    }
  },
  computed: {
    getList() {
      let filteredList = this.list

      if (this.selectedFilterByType) {
        filteredList = filteredList.filter(
          reference =>
            reference.ref_type &&
            reference.ref_type.id === this.selectedFilterByType
        )
      }

      if (this.selectedFilterByService) {
        filteredList = filteredList.filter(
          reference =>
            reference.ref_service &&
            reference.ref_service.find(
              ({ id }) => id === this.selectedFilterByService
            )
        )
      }

      if (this.selectedFilterByDistrict) {
        filteredList = filteredList.filter(
          reference =>
            reference.ref_county &&
            reference.ref_county.id === this.selectedFilterByDistrict
        )
      }

      return filteredList
    }
  },
  methods: {
    filterByType(id) {
      this.selectedFilterByDistrict = null
      this.selectedFilterByService = null
      this.selectedFilterByType = id
    },
    filterByService(id) {
      this.selectedFilterByDistrict = null
      this.selectedFilterByService = id
      this.selectedFilterByType = null
    },
    filterByDistrict(id) {
      this.selectedFilterByDistrict = id
      this.selectedFilterByService = null
      this.selectedFilterByType = null
    },
    debug(id) {
      alert('DEBUG - ', id)
    }
  },
  watch: {
    selectedFilterByDistrict() {
      this.selectedFilterByService = null
      this.selectedFilterByType = null
    }
  },
  mounted() {
    //console.log(this.list, 'list')
    // console.log(this.listType, 'listType')
    // console.log(this.listService, 'listService')
  }
}
</script>



<!--Child RegionMap-->
<script>
let pointersArr = []
for (let i = 1; i <= 14; i++) {
  pointersArr[i] = {
    filled: false
  }
}
export default {
  emits: ['update:modelValue'],
  props: ['modelValue'],
  data() {
    return {
      pointers: pointersArr
      //selectedRegion: null
    }
  },
  computed: {
    selectedRegion: {
      get() {
        return this.modelValue
      },
      set(val) {
        this.$emit('update:modelValue', val)
      }
    }
  },
  methods: {
    fill(id) {
      this.pointers[id].filled = true
    },
    unfill(id) {
      if (this.selectedRegion && this.selectedRegion === id) {
        //
      } else {
        this.pointers[id].filled = false
      }
    },
    unfillAll() {
      for (let i = 1; i <= 14; i++) {
        this.pointers[i].filled = false
      }
    },
    selectRegion(id) {
      this.selectedRegion = id
    }
  },
  watch: {
    selectedRegion(id) {
      this.unfillAll()
      if (id) {
        this.fill(id)
      }
    }
  }
}
</script>

vmodel-example.js Raw #

// App.vue
<template>
  <div id="app">
    <h3>App</h3>
    <input type="text" v-model="query" />
    <hr />
    <h3>komponenta A</h3>
    <A v-model="query" />
  </div>
</template>

<script>
import A from './components/A';

export default {
  name: 'App',
  components: {
    A,
  },
  data() {
    return {
      query: '',
    };
  },
};
</script>


// A.vue
<template>
  <div>
    <input type="text" v-model="computedQuery" />
    <hr />
    <h3>komponenta B</h3>
    <B v-model="computedQuery" />
  </div>
</template>

<script>
import B from './B';
import ComputedModel from '../mixins/ComputedModel';
export default {
  name: 'A',
  mixins: [ComputedModel],
  components: {
    B,
  },
};
</script>


// B.vue
<template>
  <div>
    <input type="text" v-model="computedQuery" />
    <hr />
    <h3>komponenta C</h3>
    <C v-model="computedQuery" />
  </div>
</template>

<script>
import C from './C';
import ComputedModel from '../mixins/ComputedModel';
export default {
  name: 'B',
  mixins: [ComputedModel],
  components: {
    C,
  },
};
</script>


// C.vue
<template>
  <div>
    <input type="text" v-model="computedQuery" />
  </div>
</template>

<script>
import ComputedModel from '../mixins/ComputedModel';
export default {
  name: 'C',
  mixins: [ComputedModel],
};
</script>


// ComputedModel.js - mixin
export default {
  emits: ['update:modelValue'],
  props: ['modelValue'],
  computed: {
    computedQuery: {
      get() {
        return this.modelValue;
      },
      set(val) {
        this.$emit('update:modelValue', val);
      },
    },
  },
};