v-if not being updated in real-time within a v-for iteration

Issue Resolved -- Solution Provided Below

I encountered an issue in Vue2 where I was attempting to manage a v-if and v-else based on an @click event within a v-for loop. However, the v-if did not dynamically change with each click as expected.

Below is the problematic code snippet (please note: the variable people is sourced from a loaded store file):

<div v-for="(person, index) in people" :key="index">
  <div @click="detailsOpened(index)">
    <PersonIcon v-if="showDetails(index)" />
    <PersonIcon2 v-else />
  </div>
</div>

import {
  each
} from 'lodash-es'

data(): {
  return {
    personMap: []
  }
}

beforeMount() {
  this.personMap = each(people, p => false)
}

methods: {
  showDetails(index: number): boolean {
    return this.personMap[index] === true
  }

  detailsOpened(index: number): void {
    this.personMap[index] = !this.personMap[index]
  }
}

Upon logging with console.log, it appeared that the detailsOpened method functioned correctly. The boolean value associated with each relevant index changed upon clicking the icon, ruling out any issues there. It seems that the v-if only executes during the initial page render and does not update dynamically when values in personMap alter. console.log confirms that the showDetails method runs only at the start of the page load, based on the size of the people array. The cause of this behavior eludes me, so any guidance would be greatly appreciated!

Edit: Solution Implemented After testing the top answer's suggestion, I encountered the console error, "Error: [vuex] do not mutate vuex store state outside mutation handlers." I transferred these methods and data to a Pinia store file and explicitly utilized "Vue.set"/"this.$set" in the store's setter, yet still received the same error. To ultimately resolve my problem, I took the following steps: 1) Transferred data and methods to a Pinia store file. 2) Employed Vue.set in the detailsOpened method within the store file. 3) Applied lodash's cloneDeep on people when initializing this.personMap.

Answer №1

As mentioned earlier: and I quote, "the showDetails method solely runs at the inception of page load". Vue lacks the knowledge of when to trigger the showDetails method a second time. Execute a method explicitly in order for it to be run.

In this scenario, consider utilizing a computed property to fulfill your desired outcome.

Answer №2

Change it to computed from method

<template>
  <div v-for="(person, index) in people" :key="index">
    <div @click="toggleDetails(index)">
      <PersonIcon v-if="isDetailsOpen(index)" />
      <PersonIcon2 v-else />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      personMap: [],
      people: [...] // initialize with your data
    };
  },
  methods: {
    toggleDetails(index) {
      this.$set(this.personMap, index, !this.personMap[index]);
    }
  },
  computed: {
    isDetailsOpen() {
      return (index) => this.personMap[index] === true;
    }
  }
};
</script>

Answer №3

Vue doesn't automatically react to direct updates made to items at their index. To ensure reactivity, you should utilize the set operator. For a deeper understanding, check out this detailed answer.

In addition, I have provided a functional demo showcasing a scenario similar to yours where I have used the set operation to update items in the personMap array.

new Vue({
  el: "#app",
  data() {
    return {
      people: [1, 2, 3],
      personMap: []
    }
  },
  beforeMount() {
    this.personMap = this.people.map(item => item = false);
  },
  methods: {
    showDetails(index) {
      return this.personMap[index] === true
    },
    detailsOpened(index) {
      this.$set(this.personMap, index, !this.personMap[index])
    },
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="(person, index) in people" :key="index">
    <div @click="detailsOpened(index)">
      <div v-if="showDetails(index)">Clicked</div>
      <div v-else>Click me</div>
    </div>
  </div>
</div>

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

Eslint has encountered a parsing error, it was not expecting that token

I encountered the issue Error: Unexpected token .. raised by eslint while working with this code snippet. Can anyone spot what's causing it? const Public = ({ loggingIn, authenticated, component, ...rest }) => ( <Route {...rest} render={(pr ...

eliminating identical items in an array

I've been working on finding and removing duplicate objects in an array, but I keep encountering an error when trying to access the filterList[i+1].tagID element. Strangely, manually inputting the [i+1] values seems to yield the correct results. I&apo ...

Prohibit communication by any means

Let's take a look at the following function overloads: function f(key: undefined); function f(key: string | undefined, value: object | undefined); I want to allow calls with a single explicit undefined argument f(undefined), but require two argument ...

A Simple Guide to Setting a Background Image in React Native with the Nativebase.io Library

What is the process for including a background image in React Native with the help of the Nativebase.io Library? I have a specific screen where I need to incorporate a background image, with all other elements positioned at the center of the image. ...

How can one effectively utilize TypeScript with native JavaScript methods and calls?

After a long break from TypeScript, I am struggling to override implementations or use native methods in the .ts file. The ones highlighted in red, excluding this, are causing errors. https://i.sstatic.net/WhcRM.png I'm not getting autocomplete sup ...

Having issues transferring the variable from JavaScript to PHP?

When attempting to pass a variable via AJAX request in JavaScript, I am encountering an issue where the variable is not being received in my PHP file. I'm unsure of where the problem lies. Can anyone help? JavaScript code var build = { m_count : ...

Challenges encountered when retrieving parameters from union types in TypeScript

Why can't I access attributes in union types like this? export interface ICondition { field: string operator: string value: string } export interface IConditionGroup { conditions: ICondition[] group_operator: string } function foo(item: I ...

The carousel spun around, each section moving to the side on its own

One issue I'm facing is that on my page, I have multiple carousel rows. However, when I click on the "next" or "prev" button to navigate through the items in the carousel, it affects all carousels instead of just the one I clicked on. I've attem ...

Learn how to run a Linux bash command by clicking a button, where the command is generated from user input

HTML: I am presenting two inputs here <input id="range3" type="range" min="0" max="255" value="0" /> <input id="num3" min="0" max="255&q ...

Learning to make a GET request from a Node application to an external API

I am currently attempting to make a GET request to an API. Below is the code I have in Angular: Service: angular.module('MyApp') .factory('Search', function($resource) { return $resource('/api/show/:search'); }); C ...

How can you set an input field to be initially read-only and then allow editing upon clicking a button using Vue.js?

//I have two divs that need to be set as readonly initially. When an edit button is clicked, I want to remove the readonly attribute and make them editable. <div> <input type="text" placeholder="<a href="/cdn-cgi/l/email-protection ...

Disable the swipe feature on a Bootstrap carousel to prevent users from navigating through slides on mobile devices. The attribute data-touch="

I've been attempting to deactivate the swipe function on my Bootstrap 4 carousel in my project, but it's proven to be quite challenging. Despite it being a basic carousel, I'm finding it difficult to turn off this feature. What am I missing ...

Transforming a PHP cURL call to node.js

Currently exploring the possibility of utilizing the Smmry API, however, it seems that they only provide PHP API connection examples. Is there anyone who could assist me in adapting it into a JS request? My requirement is simple - I just need it to analyz ...

Decoding multiple data with jQuery on the server-side

Scenario: A situation arises where I am utilizing a jQuery.ajax call to send three arrays to the server for database storage. The challenge lies in decoding the combined data object on the server side and breaking it back into the original three arrays. ...

There has been an unhandled runtime error: [object ProgressEvent] occurring with Next.js/Typescript

Exploring the world of nextJS and typescript is new to me. I am currently working on creating a simple blog using nextJS/typescript with a sanity CMS backend. Everything seems to be running smoothly during development, but then I encounter this Unhandled R ...

An HTML button generated by a .js file is able to execute a .js function without any issues, but it inadvertently removes all .css styling

Currently grappling with an issue in my JavaScript self-teaching journey that I can't seem to resolve or find examples for. The problem at hand: When the HTML button calls a .js function, it successfully executes the function but also wipes out all C ...

Adding local static files to index.html in Vue 3 can be achieved by utilizing the

<!DOCTYPE html> <html lang=""> <head> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.title %></title> <script src=" ...

The process of efficiently uploading a batch of images to Firebase storage while also obtaining all the respective

I have been using firebase storage to upload images and save their respective URLs in the firebase database. However, I recently encountered an issue with my code. In firebase v8, everything was working fine, but after updating to version 9, the following ...

Tips for selecting the right decorator for your space

I am working on developing a game that utilizes an AI. This AI's API consists of 3 methods implemented in an Angular Service Here is a simplified version of the code: app.service('AI', [function(){ return { offer: angular.noop, ...

Exploring TypeScript interfaces with optional properties and returning types

As a newcomer to TypeScript, I am currently exploring the documentation and came across an example in the "Optional Properties" section that caught my attention: interface SquareConfig { color?: string; width?: number; } function createSquare(config: ...