VueJS failing to pass parent data to child component

I'm fairly new to Vue Framework and I'm trying to figure out how to update a child component based on changes in the parent component's attributes. In the code snippet below, I've created a component that displays a greeting message based on the "name" attribute of the node passed from the parent.

Everything works fine if the "name" attribute is present when the node is initialized. However, if the name attribute is added later (as shown in the demonstration with a setTimeout function), the component throws an error and doesn't reflect the changes. I'm struggling to understand how to propagate changes for dynamic attributes generated outside the component.

Essentially, I want the component to dynamically display different widgets based on server responses tied to properties passed to it. I want the component to update itself whenever these properties change. Why isn't two-way binding working as expected in Vuejs?

Vue.component('greeting', {
    template: '#treeContainer',
    props: {'message':Object},
    watch:{
        'message': {
            handler: function(val) {
                console.log('###### changed');
            },
            deep: true
        }
    }
});

var data = {
    note: 'My Tree',
    // name:"Hello World",
    children: [
      { name: 'hello' },
      { name: 'wat' }
    ]
}

function delayedUpdate() {
    data.name='Changed World';
    console.log(JSON.stringify(data));
}

var vm = new Vue({
    el: '#app',
    data:{
        msg:data
    },
    method:{ }
});

setTimeout(function(){ delayedUpdate() ;}, 1000)
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
  <greeting :message="msg"></greeting>
</div>
<script  type="text/x-template"  id="treeContainer">
<h1>{{message.name}}</h1>
</script>

Edit 1: @Craig's answer helped me understand how to propagate changes using the "name" attribute and calling set on each attribute. But what if the data is complex and the greeting message relies on multiple attributes of the node? In real-world scenarios, widgets are based on many dynamically sent attributes from the server and each widget varies based on its type. For example, "Welcome, {{message.name}} . Temperature at {{ message.location }} is {{ message.temp}} ." Since the attributes can vary, is there a way to update the entire tree without manually traversing all nodes and calling set on each attribute? Does VUE framework offer a solution for this situation?

Answer №1

Vue has limitations in detecting property addition or deletion without using the set method (refer to: https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats). To address this issue, you can use the following code:

Vue.set(data, 'name', 'changed world')

View the JSFiddle link for a demonstration: https://jsfiddle.net/f7ae2364/

UPDATE

If you cannot watch the prop, consider implementing an event bus for communication. Begin by setting up a global bus for your component to listen on:

var bus = new Vue({});

When receiving new data, emit the event onto the bus with the updated data:

bus.$emit('data-updated', data);

To listen for this event within your component and update accordingly (using ES6), follow these steps:

created(){
   bus.$on('data-updated', (message) => {
     this.message = message;
     this.$forceUpdate();
   })
}

Check out the JSFiddle link to see this implementation: https://jsfiddle.net/9trhcjp4/

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

Transferring information to modal without using AngularUI

I'm currently working on an Angular application and facing an issue with passing data from my controller to a modal. Here is the HTML code on my index page: <!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> ... </head> & ...

The process of accessing a file object by using the file path given

Is there a way to retrieve the file object of an image that is stored in my website's folder without using "input type = "file"? The image is already saved on the website. Here is what I have tried so far: var file = new File([""], "../writeto/image. ...

When converting to a React Functional Component using Typescript, an error occurred: The property 'forceUpdateHandler' could not be found on the type 'MutableRefObject<Spinner | null>'

Looking to convert the App component in this CodePen into a Functional component using Typescript. Encountering an error when attempting to run it: ERROR in src/App.tsx:13:14 TS2339: Property 'forceUpdateHandler' does not exist on type 'Mu ...

The function queryDatabases is not supported in the DocumentDB JavaScript API

Currently, I am developing a service for Azure Functions using JavaScript/Node.js. However, I encounter an error when trying to access the function DocumentClient.queryDatabases. Despite having the correct references installed in Visual Studio Code and bei ...

Generating modal pages on the fly

One thing that's been on my mind is creating modals for my page. Typically, I would include the HTML code for my modal directly in the page like this: <div class="my-modal"> <form action="/home/index"> <input type="text" class="txt- ...

"Trouble Encountered with the dragAndDrop Function in WebdriverIO Version

I've been experimenting with different methods like dragAndDrop and performAction, but unfortunately, none of them seem to be working for the Vue.Draggable web app (for example: vuedraggable: Two Lists). Can anyone offer a solution if possible? Here ...

Leveraging the power of Google Closure Templates alongside the versatility of

We are embarking on developing an application using JavaScript and HTML5 that will utilize a rest API to access server resources, leveraging the power and convenience of jQuery which our development team is already proficient in. Our goal is to make this a ...

Trouble with X-editable: Unable to view values when editing and setting values using J

When using X-editable to modify a form with data, I encounter an issue. Initially, the values are loaded from the database to the HTML, but when users try to edit by clicking on the "Edit" button, all values appear as "Empty" instead of their actual cont ...

My search field in Safari (desktop) doesn't respond to jQuery's .focus() function

My website has a hidden search field that appears when the user clicks on the search icon. I want to automatically bring focus to the search input so users do not have to click twice. This feature works perfectly in Chrome, but not in Safari (desktop). I t ...

Showcase fullcalendar events that span across multiple rows and columns

Within my Angular application, I am utilizing the Angular UI Calendar in conjunction with Fullcalendar to display user events. Currently, when a user interacts with an event by clicking on it, only a portion of the event is highlighted. This becomes probl ...

Tips for dynamically passing parameters to functions in JavaScript?

Looking for a solution to dynamically receive input from the user in my function: divResize = { myDiv:function(width, height) {...} } divResize.myDiv(100,400); I want to make these numbers interactive and changeable based on user input. How can I achie ...

What is the best way to initiate a function from within another function while working with ReactJS?

Seeking guidance on how to trigger a Redux state change by calling a function from another function using the onClick event. Currently, I am able to invoke the Jammingmenu upon clicking an icon, however, no action is performed or alert displayed. Any assis ...

Troubleshooting issues with the sidebar navigation in Laravel project using Vue and AdminLTE

I successfully installed AminLte v3 via npm in my Laravel + vue project and everything is functioning properly. However, I am facing an issue when I attempt to click on the main menu item in the Side navbar that is labeled as <li class="nav-item has-tr ...

Experiencing trouble with detecting intersections using the Three.js raycaster

After successfully writing a code to intersect some objects, I encountered an issue when adding a canvas along with other div elements in the HTML document. Now, there seems to be no intersection on the object. You can observe this live example here. If yo ...

Activate and deactivate button

I've tried multiple examples on this site for enabling and disabling a button using javascript with jquery, but none of them seem to work for me. Here is my current dilemma: <asp:TextBox ID="mytext" runat="server" onkeyup="enableButton(this, 3)"/ ...

AngularJS: iterating through POST requests and passing each index into its corresponding response

Using AngularJS, I am attempting to execute multiple http POST requests and create an object of successfully finished requests. Here is a sample code snippet: var params = [1, 2, 3], url, i, done = {}; for (i in params) { url = '/dir ...

Steps to simulate a TouchEvent programmatically using TypeScript

Is there a way to manually trigger the touch event in TypeScript? In JavaScript, it was possible but I am struggling to achieve the same in TypeScript. For example: let touchStart: TouchEvent = document.createEvent('TouchEvent'); touchStart.i ...

Tips for seamlessly creating the animation of sketching a line

Currently, I am working on a project that involves around 40 curved lines, each containing 30 to 200 points. Despite using BufferGeometry and setDrawRange() to draw all the lines equally, only the line with over 200 points appears smooth. I attempted using ...

Difficulty triggering an event within a collection in Backbone.js

Having recently delved into JavaScript and Backbone, I encountered a puzzling error. Router = Backbone.Router.extend({ routes: { ":albumID": "load" }, load: function (albumID) { if (controller.collectionInitialized == true) ...

Begin the API server along with the React server for your React application

I'm currently working on my first React app, and I'm facing a challenge in getting both the API and the React server to start simultaneously. For client routes, I am using react-router. In a previous project, I utilized Express for setting up th ...