Trouble with binding to an array inside a Vue component instance

Trying to grasp the concepts of vue.js, but struggling with a crucial element.

The goal is to create an accordion functionality for multiple boxes (only one box displayed at a time; opening a new box closes any previously open ones). Here's the current code:

<div id="app">

  <div class="block">
    <button v-on:click="mytoggle(0,$event)">block one</button>
    <div v-if="boxes[0]">
      <p>i am box number one</p>
      <p>i am box number one</p>
    </div>
  </div>

  <div class="block">
    <button v-on:click="mytoggle(1,$event)">block two</button>
    <div v-if="boxes[1]">
      <p>i am box number two</p>
      <p>i am box number two</p>
    </div>
  </div>

  <div class="block">
    <button v-on:click="mytoggle(2,$event)">block three</button>
    <div v-if="boxes[2]">
      <p>i am box number three</p>
      <p>i am box number three</p>
    </div>
  </div>

  <pre>{{ $data | json }}</pre>

</div>

and included script:

var vm = new Vue({
    el: '#app',

    methods: {
        mytoggle: function (n, event) {
            event.preventDefault();
            for(var i = 0; i < 3; i++) { // close all boxes
                this.boxes[i] = false;
            }
            this.boxes[n] = true; // open the corresponding box
            console.log(n);
        }
    },

    data: {
        boxes: [false,true,false]
    }
});

Upon loading the page, the second box is displayed (correct due to the true value in the second element of the boxes array).

However, clicking on the buttons does not update the boxes.array or display the boxes accordingly. The log output confirms the script is functioning correctly when buttons are clicked. It seems like there might be an issue with the binding process. Any guidance on resolving this would be greatly appreciated.

Answer №1

Give this a shot:

HTML:

<div id="content">

  <div class="box">
    <button @click.prevent="toggleBox(0)">Box One</button>
    <div v-show="boxes[0].isVisible">
      <p>This is box number one</p>
      <p>This is box number one</p>
    </div>
  </div>

  <div class="box">
    <button @click.prevent="toggleBox(1)">Box Two</button>
    <div v-show="boxes[1].isVisible">
      <p>This is box number two</p>
      <p>This is box number two</p>
    </div>
  </div>

  <div class="box">
    <button @click.prevent="toggleBox(2)">Box Three</button>
    <div v-show="boxes[2].isVisible">
      <p>This is box number three</p>
      <p>This is box number three</p>
    </div>
  </div>

  <hr/>

  <pre>{{ boxes | json }}</pre>

</div>

Vue:

var app = new Vue({
    el: '#content',
    data: {
        boxes: [{isVisible:false},{isVisible:true},{isVisible:false}]
    },
    methods: {
        toggleBox: function (index) {  
            for(var i = 0; i < 3; i++) { // close all boxes
                app.boxes[i].isVisible = false;
            }
            app.boxes[index].isVisible = true; // open the corresponding box
        }
    }
});

Fiddle: https://jsfiddle.net/username/123456789/

UPDATE:

You could also simplify your toggleBox method to modify array values using Vue's $set:

toggleBox: function (index, event) {
    event.preventDefault();
    for(var i = 0; i < 3; i++) { // close all boxes
        this.boxes.$set(i, false);
    }
    this.boxes.$set(index, true); // open the corresponding box
    console.log(index);
}

Answer №2

It is recommended to utilize the $set method instead of directly modifying data. [source]

You can also implement a simpler solution like the following:

new Vue({
  el: '#app',
  data: {
    selected: 1
  },
  methods: {
    select (index) {
      this.selected = index
    },
    isSelected (index) {
      return this.selected === index
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.24/vue.min.js"></script>

<div id="app">
  <div class="block">
    <button @click="select(0)">block one</button>
    <div v-show="isSelected(0)">
      <p>i am box number one</p>
      <p>i am box number one</p>
    </div>
  </div>

  <div class="block">
    <button @click="select(1)">block two</button>
    <div v-show="isSelected(1)">
      <p>i am box number two</p>
      <p>i am box number two</p>
    </div>
  </div>

  <div class="block">
    <button @click="select(2)">block three</button>
    <div v-show="isSelected(2)">
      <p>i am box number three</p>
      <p>i am box number three</p>
    </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

Basic asynchronous JavaScript and XML (AJAX) call

I am currently learning about ajax and experimenting with a script that involves extracting information from a JSON object and displaying it on the document. Below is an example of the JSON file named companyinfo.json: { 'id':1, 'name&apos ...

Automatically choose radio buttons within an li element in a loop

Hey there, I'm new to SO and this is my first question. As a bit of a newbie, I found this jquery code snippet on another SO answer that I want to use. The function I'm aiming for is the same, but the markup structure in my HTML is different bec ...

Close specific child python processes as needed, triggered by a jQuery event

Having trouble managing child processes independently without affecting the main parent process in a web client using jQuery? Look no further. Here's my scenario: I've got a Flask server hosting a basic webpage with a button. Clicking the button ...

When injected, the reactive variable returns an undefined value

I am currently working with Vue3 utilizing the options API. In the code snippet below, I have a provider component where I provide a reactive version of the object isToggleBtnLabelDigitizePolygon. Initially, the value of isToggleBtnLabelDigitizePolygon is ...

Angular Oops! We ran into a small hiccup: [$injector:modulerr]

I am facing an issue with an angular js error angular.js:36 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.19/$injector/modulerr?p0=app&p1=Error%3A%20…gleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.2.19%2Fangular.min.js%3A18%3A139) ...

jquery counter is malfunctioning

I noticed a strange issue with the counters on my website. They count up as expected when the page loads, but for some reason, when the screen width shrinks below 800px, they don't start automatically. However, if I quickly scroll to where the counter ...

Having trouble accessing the property '_wrapper' of an undefined object when using vue multiselect

Encountering an issue with VUE-MULTISELECT Here is the code snippet: <b-modal id="skills"> <div> <label class="typo__label">Tagging</label> <multiselect v-model=&q ...

Attempting to access a shared php/javascript library using mod_rewrite

Let's dive into a fresh perspective on a question I previously raised: I've crafted a mod_rewrite snippet that checks for the existence of JavaScript, CSS, and PHP files on the subdomain they are called from (e.g., subdomain.example.com). If the ...

unable to modify the content within a div by clicking on a link

Lately, I've been experimenting with a code snippet I found on this fiddle: http://jsfiddle.net/unbornink/LUKGt/. The goal is to change the content of a div when clicking on links to see if it will work on my website. However, no matter which link I c ...

Node.js: Experiencing HTTP request timeout issues lasting for over a minute

Using Node.js (version 0.10.28), I encountered an issue when making an http.request to my Ruby API for a large amount of data. The request seems to time out and return a 404 error after only 1 minute. Interestingly, when using other methods like wget or jQ ...

The computed property in Vue JS is providing an unexpected output

I need assistance with a task in Vue JS that I'm struggling with. I can't seem to figure out what's causing the issue in this code. The task involves creating a dynamic table with 5 columns, each with a background color of red, blue, yellow ...

A specialized HTTP interceptor designed for individual APIs

Hey there, I am currently working with 3 different APIs that require unique auth tokens for authentication. My goal is to set up 3 separate HTTP interceptors, one for each API. While I'm familiar with creating a generic httpInterceptor for the entire ...

An error was encountered when trying to read property '0' of an undefined object in a for loop

Currently, I am working on a project to create a mastermind game. Everything is progressing smoothly, except for one issue that keeps popping up - I keep encountering the error: "uncaught typeerror cannot read property '0' of undefined." fun ...

What methods can I use to minimize the duration of invoking the location.reload() function?

When I'm using window.location.reload() in my onClick() function, it's taking too long to reload. I tried modifying the reload call to window.location.reload(true) to prevent caching, but it's still slow. The issue seems to be with location. ...

AngularJS and ExpressJS clash in routing (Oops, Crash!)

When setting up routing in angularjs and expressjs, I have created app.all('/*'...) to enable rendering index.html. However, whenever I use /*, the page crashes with an "Aw, Snap!" message. angularjs home.config(function($routeProvider,$locatio ...

Exploring JavaScript functions within the Rails 4 asset pipeline directory

I am facing an issue while trying to use a JavaScript function through the Chrome Console after embedding that function within the Rails Asset Pipeline Manifest. To achieve this, I followed these steps to create and set up a basic Rails 4.2.4 App: $ rails ...

Custom div element obstructs information window on map due to lack of auto panning feature

I created a unique div that is absolutely positioned on a Google Map. You can view the image below to see it. My issue is that the info window is being covered by this custom div element, as demonstrated in the picture. https://i.stack.imgur.com/1TgyQ.jpg ...

Tips for assigning a value in a dropdown menu with AngularJS

Can someone help me with setting the same value in multiple drop-down lists using angular.js? Below is an explanation of my code. <table class="table table-bordered table-striped table-hover" id="dataTable"> <tr> <td width="100" align ...

Performing AJAX requests to dynamically update multiple DIVs

Encountering difficulties with adding additional input fields to a page, each of which contains jquery code for appending more select boxes related to them. The base html setup is as follows: <p id="add_field"> … </p> <div class="show_sub ...

Vue: Simple ways to retrieve state data in MutationAction

I'm having trouble accessing the state inside @MutationAction Here is the setup I am using: Nuxt.js v2.13.3 "vuex-module-decorators": "^0.17.0" import { Module, VuexModule, MutationAction } from 'vuex-module-decorators' ...