How can I refresh an HTML element when a value in a multi-dimensional array changes?

I'm facing an issue with a v-btn component that gets its content from values deep inside a multi-dimensional array.

<div v-for="student in students"> 
    <v-btn disabled v-for="tag in student.tags">{{tag}}</v-btn>
</div>

In this case, tags is a sub-array. I'm trying to update the button whenever these values change, but I'm unsure of how to achieve this. I've attempted using Vue.set as shown below:

// "this.students" is an array, and "this.students[index].tags" is a sub-array.
// I increase the length of the sub-array.
this.students[index].tags.length++;

// Next, I insert a new value at the end of the sub-array.
Vue.set(this.students[index].tags, this.students[index].tags.length - 1, value)

Although I can see the values and the length of the sub-array, this.students[index].tags, changing when I print them to the console, the new button doesn't appear. Only after re-compiling the client-end does the new button show up.
Could someone guide me on how to re-render that button? Thanks in advance!

Answer №1

Vue.js only observes the properties of an object within one level deep, meaning it will not detect changes deeper than that. To work around this limitation, you can consider a few solutions:

  • Trigger a force update using this.$forceUpdate(); (https://v2.vuejs.org/v2/api/#vm-forceUpdate)
  • Use
    this.$set(this.students[index], 'tags', this.students[index].tags.concat([value]));
    to ensure Vue observes the changes in the 'tags' array
  • Implement a hash-map for managing students' tags efficiently
computed:
{
  studentTags()
  {
    const result = {};
    this.students.forEach(student =>
    {
      result[student.id] = student.tags;
    });
    return result;
  }
},
methods:
{
  addTag(studentId, tag)
  {
    this.studentTags[studentId].push(tag);
  }
}

Answer №2

Utilizing Vue.set to push new data into an array or sub-array is unnecessary as it is automatically handled by vuejs. However, employing Set is recommended to reflect updates within a sub-array.

Consider the following example-

<template>
  <div id="app">
    <div v-for="(student, index) in students" :key="index">
     <button @click="addMoreTag(student.id)" style="background: green">
      Add more
     </button>
     <button
      v-for="(tag, tindex) in student.tags"
      :key="tindex + 't'"
      @click="updateTag(student.id, tag)"
     >
      {{ tag }}
     </button>
   </div></div></div>d;
<scriptt>
 export defaault {
 nname: "App",

   dat:a() {
     return {
      studennts: [
      {
       id: 1,
       name: "John",
       tags: ["one", "two"],
      },
      {
       id: 2,
       name: "Mira",
       tags: ["three", "five"],
      },
     ],
   };
  },

 mmethods: {
   addMoreTaag(id) {
    let index = this.students.finndIndex((item) => item.id === id);
    this.sstudents[index].tags.push("new");
   },

   updateTagg(student_id, tag) {
    let index = his.students.findIndex((item) => item.id === student_id);
    let taagIndex = this.students[index].tags.findIndex(
      (item) => item === tag
    );
    this.$set(this.students[index].tags, tagIndex, "updated");
   },
 },
};

I also published on codepen here - https://codesandbox.io/s/blissful-cdn-5kyt1c?file=/src/App.vue

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

The preventDefault method is failing to prevent the default action when placed within a

I am having trouble using preventdefault to stop an action. I'm sorry if the solution is obvious, but I can't seem to locate the mistake. Why isn't it preventing the link from being followed? Here is a link to my jsfiddle: http://jsfiddle.ne ...

Incorporating a new row in JQuery Datatable using an mdata array

I am currently using a datatable that retrieves its data through mData. var processURL="path" $.ajax( { type : "GET", url : processURL, cache : false, dataType : "json", success ...

When transferring files to the src/pages directory in Next.js, the custom _app and _document components are not recognized

The documentation for Next.js mentions that the src/pages directory can be used as an alternative to /pages. However, I encountered a problem when moving my custom _app.tsx and _document.tsx files into the src folder, as they were being ignored. If you cr ...

Looking for a simple method to display a popover using conditional if/else statements?

On my website, I am utilizing JavaScript to determine the user's Facebook status. This includes checking if the user is already logged in and has allowed our app, if they are logged in but haven't authorized our application, or if they are not lo ...

Is there a way to use a single function to fill and calculate multiple input fields with PHP, Javascript, and

I've encountered an issue while trying to populate a form using Javascript/ajax/php. The problem is that my function only fills in one of the required forms and then stops, even though I have received the second response from the server. Here's ...

if the arguments for a javascript function are not provided

Currently, I am in the process of learning JavaScript through a book called "Visual Quickstart Guide". However, I have encountered a challenge with understanding the logic behind a particular code snippet. In the function definition below, it appears that ...

js expressive dynamic pattern matching

Hey there! I'm in the process of coding an online store and am currently focusing on implementing the add to cart functionality. My goal is to save product IDs and their quantities in a cookie, which will look something like this: id1:qt1,id2:qt2... I ...

The presence of a default value within an Angular ControlValueAccessor triggers the dirty state due to

My task is to create dynamic Input components for a template driven form using a directive. The default value of the Input component should be set by the component itself. However, I encountered an issue where setting a default value automatically marks t ...

Creating a visually appealing multi-bar chart in AngularJS: Tips for effectively presenting data

Imagine that I have the JSON data below: [ { month: "Jan", cost: 80, energy: 90 }, { month: "Feb", cost: 50, energy: 80 }, { month: ...

Encountering difficulties with installing bootstrap-vue

While attempting to integrate Bootstrap-Vue into my project that includes Vuex, Vue-Router, TypeScript, and Babel, I encounter an error in the browser. To replicate docker run -it --rm -p 8080:8080 node:17.7.2-alpine yarn global add @vue/cli vue create ...

Create a generic function that retrieves a specific property from an array of objects using the select method

Currently, I have implemented four functions that select entries from an array based on different properties. if ($scope.filters.filter1) $scope.filteredEntries = $scope.filteredEntries.filter(function (o) { return o.field1 === $scope.filt ...

Issue with bootstrap: the ID is not activating even when it is visible

I am a beginner with bootstrap and I encountered an issue. I created a simple page using bootstrap 5 and included 4 buttons: "Home," "Explore," "Create," and "Share." Here is the code for reference: https://github.com/nguyencuc2586/project2 In the code s ...

Efficiently finding a group of substrings within a JavaScript string

I am currently working on a method to efficiently search for specific substrings within a given string. Here is my current implementation: const apple = "apple" const banana = "banana" const chickoo = "chickoo" const dates = & ...

Error encountered: The object 'Sys' is not defined in the Microsoft JScript runtime

I currently have a webpage with the following code snippet: <script type="text/javascript" language="javascript"> /// <reference name="MicrosoftAjax.js" /> Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler ...

Creating unique ID tags using AngularJS

I am struggling with creating an HTML structure that looks like this: <ul> <li id="r1_1">Root node 1 <ul> <li id="child_node_1">Child node 1</li> <li id="child_node_2">Child node 2</ ...

How can I maintain the selected state of checkbox and radio button in ReactJS after page refresh?

I am facing an issue with my multistep form that contains radio buttons and checkboxes from material UI. Although the data is stored correctly in state and local storage, when I move to the next page and then return, the selections appear unselected to the ...

Top strategy for monitoring a user's advancement in reading different text segments

If you are familiar with zyBooks, I am looking to implement a similar feature where users can track the sections they have read and mark them as completed with a button. However, I am struggling conceptually with determining how best to structure my mongo ...

Best practices for passing multiple values with keys in vue.js when constructing URLs

I am working with this data containing various attributes: for(var k = 0;k<this.form.fields.length;k++) { this.dynamic_fields.push({attribute_id:attributes[k].id,value: attributes[k].value}) ...

It is not possible to utilize a JavaScript function once the script has been loaded through

I am attempting to programmatically load a local JavaScript file - PapaParse library, and then utilize one of its functions: $.getScript("./Content/Scripts/papaparse.js", function () { console.log("Papaparse loaded successfully"); Papa.parse(file, ...

Unable to display api results in React using console.log

I'm having an issue with my console log not displaying the API results. Can someone help me figure out what's wrong? I'm new to React, so any guidance would be appreciated. componentDidMount() { this.setState({ loading: true }) cons ...