In Vue, reactivity does not extend to nested child objects

I am dealing with JSON data structured like this-

items: {
  id: 1,
  children: [{
    id: 2,
    parentId: 1,
    children: [{
      id: 3,
      parentId: 2
    }]
  }]
}

level-1 children represent parent items that all possess a parent_id of 1 (the root node's id), and level-2 children are child items with a parent_id corresponding to their respective level-1 child's id.

With this data, my goal is to construct a tree-view user interface using Vuetify where each parent and child item in the tree can be edited. Refer to the UI image for visualization:

https://i.stack.imgur.com/N0W96.png

Issue Encountered-

The parent items update successfully, but there seems to be an issue with updating the child items. Particularly problematic is this sequence of steps:

  1. Update any child initially (works)
  2. Then update its parent (works)
  3. Attempt to update the child again (not working)

Approach to Updating-

I locate the item indexes based on their ids and update the item at that index utilizing Vue.set. While I observe the data updating within the array, it does not reflect the updates in the template.

Below is a demonstration. If you find the logic convoluted, kindly suggest an alternate approach. As of now, this is the only method I could come up with.

Vue.component('my-dialog', {
  // Component structure omitted for brevity
})

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data() {
    return {
      dialog: false,
      edit_item: {},
      items: {"id":1,"title":"Root","children":[{"id":2,"parentId":1,"title":"Chapter 1","children":[{"id":3,"parentId":2,"title":"Sub-chapter 1.1"},{"id":4,"parentId":2,"title":"Sub-chapter 1.2"}]},{"id":5,"parentId":1,"title":"Chapter 2","children":[{"id":6,"parentId":5,"title":"Sub-chapter 2.1"},{"id":7,"parentId":5,"title":"Sub-chapter 2.2"}]}]}
    }
  },
  methods: {
    showDialog(payload) {
      // Method implementation omitted for brevity
    },
    onUpdate(payload) {
      // Update logic implementation omitted for brevity
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<head>
  <link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/css/materialdesignicons.min.css" rel="stylesheet">
</head>
<div id="app">
  <v-app id="inspire">
    // HTML template section containing components for editing
  </v-app>
</div>

Answer №1

If you want to streamline the process, consider utilizing Vue.set and managing the updated fields in the dialog's event.

<div id="app">
  <v-app id="inspire">
    <div>
      <my-dialog :dialog="dialog" :prop_item="edit_item" @on-update="onUpdate"></my-dialog>

      <v-treeview :items="items.children" item-text="title">
        <template v-slot:prepend="{ item }">
          <v-icon @click.stop="showDialog(item)">mdi-pencil</v-icon>
        </template>
      </v-treeview>
    </div>
  </v-app>
</div>
Vue.component("my-dialog", {
  template: `<v-dialog :value="dialog" persistent><v-card><v-text-field v-model="form.title"></v-text-field></v-card><v-btn @click="$emit('on-update', form)">Save</v-btn></v-dialog>`,
  props: {
    dialog: {},
    prop_item: {}
  },
  data() {
    return {
      form: {
        title: null
      }
    };
  },
  watch: {
    dialog(value) {
      if (value) {
        Object.keys(this.prop_item).forEach((key) => {
          this.$set(this.form, key, this.prop_item[key]);
        });
      }
    }
  }
});

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data() {
    return {
      dialog: false,
      edit_item: {},
      items: {
        id: 1,
        title: "Root",
        children: [
          {
            id: 2,
            parentId: 1,
            title: "Chapter 1",
            children: [
              { id: 3, parentId: 2, title: "Sub-chapter 1.1" },
              { id: 4, parentId: 2, title: "Sub-chapter 1.2" }
            ]
          },
          {
            id: 5,
            parentId: 1,
            title: "Chapter 2",
            children: [
              { id: 6, parentId: 5, title: "Sub-chapter 2.1" },
              { id: 7, parentId: 5, title: "Sub-chapter 2.2" }
            ]
          }
        ]
      }
    };
  },
  methods: {
    showDialog(payload) {
      this.edit_item = payload;
      this.dialog = true;
    },

    onUpdate(form) {
      Object.keys(form).forEach((key) => {
        this.$set(this.edit_item, key, form[key]);
      });

      this.dialog = false;
    }
  }
});

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

Discover the magic of Google Charts with the ability to showcase HTML source code within tooltips

I am attempting to show a Pie Chart using Google Charts with HTML in the tooltips, but I am encountering an issue where the HTML source is visible. I have tried setting html:true on the data column and tooltip.isHtml in the options, but I am unsure of what ...

View Preview Image using the following image tag in JavaScript

I am trying to display an image preview using the img tag that is placed after my input field. Here is my HTML: <input name="image" type="file" id="uploadImage" onchange="PreviewImage(this);" /> ...

Executing the event handler only once

In my React project, I have a button that toggles a boolean state. However, I realized that the button can both set and unset the state due to its toggle functionality. I only want the state to be changed once. Is there a different function I can use ins ...

Substitute the colon in JavaScript prior to submitting the form

I am currently working on a text input search field where I want to automatically add an escape backslash to any colon entered by the user. Below is the code snippet I have implemented so far: <form role="form" action="..." method="get"> <div ...

Struggling to send information using Angular $resource?

I've been working on sending data to an API using Angular's $resource. Currently, I can successfully retrieve data from my test server using a GET request or querying. However, I'm having trouble figuring out how to send new data to the serv ...

Using jQuery to dynamically add a value to a comment string

Is there a way to dynamically include tomorrow's start and end times in the message for the setupOrderingNotAvailable function if today's end time has passed? The current message states that online ordering will be available again tomorrow from 1 ...

Struggling with effectively executing chained and inner promises

It seems like my promises are not completing as expected due to incorrect handling. When using Promise.all(), the final result displayed with console.log(payload) is {}. Ideally, it should show something similar to this: { project1: { description: & ...

Is it advisable to load 10,000 rows into memory within my Angular application?

Currently, I am in the process of creating a customer management tool using Angular.js that will allow me to directly load 10,000 customers into the $scope. This enables me to efficiently search for specific data and manipulate it without the need for serv ...

The importance of variables in Express Routing

I'm really diving into the intricacies of Express.js routing concepts. Here's an example that I've been pondering over: const routes = require('./routes'); const user = require('./routes/user'); const app = express(); a ...

Transform my Curl script into a NodeJS app

I'm trying to replicate the functionality of a curl command within my NodeJS application, but I am facing some difficulties. Any guidance on how to achieve this would be greatly appreciated. curl -H "Authorization: bearer $TOKEN" If I already hav ...

Tips for creating a countdown timer from scratch without relying on a plugin

Looking at this image, it is clear that jQuery can be used. However, I am wondering if there is a way to create a countdown timer without relying on plugins. Can anyone offer some guidance? ...

Delete items within the first 10 minutes of shutting it down

Is there a way to temporarily remove a newsletter element for 10 minutes after closing it on a webpage? The idea is that once the panel is closed, it should stay hidden even if the page is refreshed within that timeframe. I was considering using local stor ...

Understanding Json data using Jquery

I am currently learning about Jquery, Ajax, and JSON but I am having difficulty with parsing Json data. Despite researching extensively on stackoverflow Parsing JSON objects for HTML table Access / process (nested) objects, arrays or JSON Parse JSON in ...

Identifying the various types in Typescript

In the process of developing a solution for Excel involving data from an Office API, I encountered the challenge of distinguishing between different types that a function can return. Specifically, the data retrieved as a string may belong to either a "Cell ...

Step-by-step guide on invoking a recursive function asynchronously in JavaScript

As I delved into the realm of creating a unique Omegle clone using Node.js and Socket.io for educational purposes, I encountered a challenge that has left me scratching my head. The socket ID of clients along with their interests are stored in an array of ...

[Vue Alert]: Render Error - "TypeError: Unable to retrieve the 'getters' property of an undefined object"

Here is the code snippet from my app.js file. Can someone please review it and confirm if I have defined the items correctly according to the Vuex documentation? import store from "./store"; require('./bootstrap'); window.Vue = require( ...

Tips for converting a base64 encoded string to a normal string in Swift

Obtaining the readme data for a selected repository from the GitHub api has proven to be a challenge. The "content" seems to be in base64 format, and while attempting to convert it I encountered a fatal error: "Fatal error: Unexpectedly found nil while unw ...

Fixing My Code with JQuery Tabs and Hyperlinking

I have come across a problem while using multiple pages with jQuery tabs. Let's consider Page1.html with #tab1 and #tab2, and Page2.html with #tab3 and #tab4. Here are the issues I am facing: 1) Within the tab content of Page1.html#tab2, there is a h ...

A guide on storing user inputs in a config or JSON file for future retrieval

My function involves retrieving user input to correct column names in a dataset that do not match the master dataset. For instance, if the master dataset has columns X, Y, Z but the child dataset uses A, B, C. I prompt the user to input the correct names ...

Decode JSON data in PHP for Joomla via the json_decode function

Looking for some assistance with decoding a JSON file in my database. Here is the data: {"img":["images/logo2.png","images/logo.png"]} I am trying to display the images like this: images/logo2.png images/logo.png ...