Synchronize data bidirectionally between parent and child components in Vue 2

This special wrapper I created for the Vue-multiselect package acts as a child component within this scenario.

<template>
    <div>
        <multiselect
            v-model="items"
            :options="filteredList"
            :multiple="multiple"
            :close-on-select="multiple ? false : true"
            :show-labels="false"
            :placeholder="placeholder"
            track-by="id"
            :label="label"
            @input="inputChanged"
            :internal-search="false"
            @search-change="searchItems"
        >
        </multiselect>
    </div>
</template>

<script>
    export default {
        model: {
            prop: 'parentItems',
            event: 'change',
        },
        props: ['multiple', 'list', 'placeholder', 'label', 'parentItems'],
        data() {
            return {
                items: this.parentItems,
                filteredList: this.list,
            }
        },
        methods: {
            searchItems(query) {
                let q = latinize(query.toLowerCase().replace(/\s/g,''))
                this.filteredList = this.list.filter(li => latinize(li[this.label].toLowerCase().replace(/\s/g,'')).includes(q))
            },
            inputChanged() {
                this.$emit('change', this.items)
                this.$emit('filters-changed')
            },
            resetItems() {
                this.items = this.multiple ? [] : null
            },
        },
    }
</script>

The parent element structure is as follows:

<custom-multiselect
    v-model="car"
    :multiple="false"
    :list="cars"
    placeholder="Car"
    label="pseudo_id_name"
></custom-multiselect>

I am considering not using items and only relying on parentItems, which triggers a warning:

[Vue warn]: Avoid mutating a prop directly since the value
will be overwritten whenever the parent component re-renders.
Instead, use a data or computed property based on the prop's value. Prop being mutated: "parentItems"

What exactly triggers a parent component to re-render? In my tests, this setup solved synchronization without any issues. If using the prop as data was acceptable in my case, is there a way to suppress this warning?

If this approach is still incorrect, I would appreciate guidance on how to ensure proper synchronization of items. Despite researching similar issues on Stack Overflow, I'm still unclear about the solution.

Currently, with my v-model setup, changes are properly emitted to the parent. However, I am facing challenges implementing synchronization in the opposite direction.

For instance, when the parent calls resetForm() to set this.car = null, the child component is unaware that items should also become null. How can I listen for this event effectively?

Answer №1

To ensure smooth data flow between parent and child components, consider using a computed property with getter and setter methods for the 'items' prop. This way, you can bind it to the child component's model using v-model="items". In cases where 'parentItems' is mandatory, this approach works effectively by guaranteeing that the custom component always receives the necessary prop. However, if 'parentItems' were optional, it may be preferable to retain a duplicate in the component's data along with an appropriate default value, triggering a change event through a watcher as originally suggested.

computed: {
  items:{
    get(){
      return this.parentItems;
    },
    set(value){
      this.$emit('change', value);
    }
  }
}

Answer №2

It appears that adding this to the child element is effective. If there is a more streamlined method, I am open to suggestions.

watch: {
    parentItems: function (val, oldVal) {
        this.items = this.parentItems
    }
},

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Switch up Google Fusion URL using Jquery

Looking to modify Google Fusion query using jQuery, here is the code snippet: var fusionid= ""; function initMap() { var map = new google.maps.Map(document.getElementById('map-canvas'), { center: {lat: 28.3268, lng: 84.1855}, zoom: 7 } ...

Dynamic change in the mutation observer is not causing the callback to trigger

I have created a nested structure with two <div> elements. I am monitoring changes in the width of the inner <div>, which is set to width:auto;. Despite adjusting the width of the parent <div>, the mutation observer callback doesn't ...

Having trouble with the npm Twitter API functionality?

I'm attempting to execute a simple stream using an example code snippet. Here is the code I am working with: var twit = require('twitter'); var twitter = new twit({ consumer_key: '[KEY]', consumer_secret: &ap ...

Coloring vertices in a Three.js geometry: A guide to assigning vibrant hues

This inquiry was previously addressed in this thread: Threejs: assign different colors to each vertex in a geometry. However, since that discussion is dated, the solutions provided may not be applicable to current versions of three.js. The latest versions ...

Ensuring a value is fully defined before passing it as a prop in a component

Is there a way to handle passing down state as a prop in a React component that is being fetched from an API using useEffect and axios? The state is initially set to "null", and I am encountering issues when trying to pass it down as a prop before it is ...

The Bootstrap modal fails to appear when closed

After opening and closing the modal window, clicking on the button does not display the modal window again. The screen remains grayed out and the content of the modal window does not appear. yyyyyyyyyyyyyyyy function customShortcode() { ob_start(); ...

Steps for running a TypeScript project as a child process within a JavaScript project

I am facing an issue with integrating my Electron app, written mainly in JavaScript, with an Express server project built in TypeScript. When I attempt to create a child process of the TypeScript project within my electron.js file, I encounter TypeScript e ...

Using Ajax/jQuery in combination with Mongodb

My experience with Ajax/jQuery is fairly new. I am currently working on creating a sample HTML page using Ajax/jQuery to retrieve all customers and search for a customer by ID. Each customer has three variables: ID, firstName, and lastName. I am looking t ...

Tips for ensuring that the toJSON method in Sails.js waits for the find operation to complete before returning the object

When I try to run a find inside the toJSON function in the model, the object is returned before the find completes. How can I ensure that the return happens only after the find operation has completed? toJSON: function() { var obj = this.toObject(); Com ...

Sorting in MongoDB v3.6 is a breeze with the powerful capabilities that the

I'm encountering an issue with arranging the most recently added item in a list of objects/items to display at the top. It's similar to a job board where I want the newest jobs to appear at the top rather than at the bottom. I attempted to use Po ...

Tips for managing page navigation and incoming links on a site that uses only ajax technology

Currently, I am in the process of developing a fully ajax-based website which presents a challenge - the inability to provide direct page links. To address this, I have implemented a functionality where the page name gets appended to the URL each time an a ...

Is it possible to implement localStorage for auto-filling multiple forms simultaneously on a single webpage

I have been exploring a code snippet by Ke Yang that uses localStorage to synchronize text in form fields across different fields. I am interested in implementing something similar. On a page where I have a library of downloadable items, there are approxi ...

Is it possible to set a read-only attribute using getElementByName method

To make a text field "readonly" by placing JavaScript code inside an external JS file, the HTML page cannot be directly modified because it is located on a remote server. However, interaction can be done by adding code in an external JS file hosted on a pe ...

"Enhance the visual appeal of your Vue.js application by incorporating a stylish background image

Currently, I am utilizing Vue.js in a component where I need to set a background-image and wrap all content within it. My progress so far is outlined below: <script> export default { name: "AppHero", data(){ return{ image: { bac ...

Trouble updating Kendo DropDown in Internet Explorer

Having an issue with updating a Kendo DropDownList through a javascript function. It works fine in FireFox and Chrome, but not in Internet Explorer. @(Html.Kendo().DropDownList() .Name("myDDL") .HtmlAttributes(new { style = "width: 320px" }) . ...

When receiveMessage is triggered, the FCM push notification fails to refresh the view

After following this helpful tutorial on Push Notifications with Angular 6 + Firebase Cloud Messaging, everything is working perfectly. I am able to receive notifications when using another browser. To ensure that my notification list and the length of no ...

Is it possible to observe cross-domain Javascript requests in Firebug or any alternative browser extension?

Is there a way to monitor cross-domain JavaScript requests made on a webpage? Is it possible with Firebug or any other plugin? Consider this scenario: If I visit stackoverflow.com and they incorporate an external JavaScript file (such as Google Analytics) ...

What is the method to change between input sources in php?

Imagine this scenario: when a user clicks on a specific button, I want them to be presented with either a dropdown list or an input field. This decision would allow the user to choose an existing item or create a new one. <select name="choose[rowId]"&g ...

Issues arising when attempting to replicate a fetch object into an undefined object in React.js

I'm facing an issue where I have defined a 'poke' object and when I try to clone an object into it, I only get a promise fulfilled with the object's link , instead of the actual object. Here's the code snippet: let poke = fetch(url ...

The header row in my table multiplies each time an AJAX call is made

HeaderRowMultiplesEachTimeAjax My web grid table in JavaScript consists of a complete HTML table. The top header, which acts like a colgroup caption table, is built through JavaScript insertion as shown below: var headerRow = "<tr><th colspan=&a ...