Vue, list reordering acts strangely when selecting the displayed checkbox

I am facing a perplexing issue that has me stumped. Despite my attempts to replicate the error, the code below seems to be functioning perfectly!

Here is what is expected to occur:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
    <middleman :items="items" :selected="selected" @update="update"></middleman>
</div>

<script type="text/x-template" id="checkbox">
    <label :for="$vnode.key">
        {{ value }}
        <input type="checkbox"
               :value="value"
               :id="$vnode.key"
               @change="$emit('update', $event)"
               :checked="isSelected(value)">
    </label>
</script>

... (Code continues)

The above snippet represents the structure of my code. It consists of a root component, a middleman, and then individual checkboxes...

However, my implementation is resulting in this unexpected behavior: https://i.sstatic.net/rnssk.gif

Let's take a look at the similar code utilizing single-file components:

// Root.vue

<template>
    <div class="app-search">
        <div class="app-search__facets">

            <facet v-for="(facet, key) in facets"
                   @update="updateFacet(...$event, key)"
                   :facet="facet"
                   :label="key"
                   :data="items[key]"
                   :key="key"/>
        </div>
   </div>
</template>

... (Code continues)
// Facet.vue

<template>
    <div class="app-search__facet">
        <p class="app-search__facet--title">{{ label }} ({{ selected }})</p>
        <component :is="facet.control"
                   v-for="(value, index) in filter"
                   :data="value"
                   :value="facet.selected"
                   :key="`facet-${label}-${index}`"
                   @value="update($event)" />
    </div>
</template>

... (Code continues)
// Checkbox.vue

<template>
    <label :for="$vnode.key" class="app-search__checkbox">
        {{ data.value }} ({{ data.count }})
        <input type="checkbox"
               :id="$vnode.key"
               :value="data.value"
               @change="$emit('value', $event)"
               :checked="isSelected">
    </label>
</template>

... (Code continues)

Can anyone shed some light on what might be causing this discrepancy?

Answer №1

The issue arises from utilizing v-for index to generate a :key and arranging items post each select/deselect action. Avoid using index in key - opt for something distinct for each item, like item.value

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
    <middleman :items="items" :selected="selected" @update="update"></middleman>
</div>

<script type="text/x-template" id="checkbox">
    <label :for="$vnode.key">
        {{ value }}
        <input type="checkbox"
               :value="value"
               :id="$vnode.key"
               @change="$emit('update', $event)"
               :checked="isSelected(value)">
    </label>
</script>

<script type="text/x-template" id="middleman">
    <div>
        <checkbox v-for="(item, index) in filtered"
                  :selected="selected"
                  :value="item.value"
                  @update="$emit('update', $event)"
                  :key="item.value"></checkbox>
    </div>
</script>

<script>
    Vue.component('checkbox', {
        props: ['value', 'selected'],
        template: '#checkbox',
        methods: {
            isSelected(value) {
                return this.selected.indexOf(value) > -1;
            }
        }
    })
    Vue.component('middleman', {
        props: ['items', 'selected'],
        template: '#middleman',
        computed: {
            filtered() {
                return [...this.items].sort((a, b) => this.selected.includes(b.value) - this.selected.includes(a.value))
            }
        }
    })

    new Vue({
        el: '#app',
        data: {
            items: [
                {value: 'BMW', count: 1},
                {value: 'AUDI', count: 1},
                {value: 'VAUXHALL', count: 1},
                {value: 'FIAT', count: 1},
                {value: 'HONDA', count: 1},
                {value: 'LANDROVER', count: 1},
            ],
            selected: ['AUDI', 'HONDA']
        },
        methods: {
            update(event) {
                if (event.target.checked) {
                    this.selected.push(event.target.value);
                    return;
                }
                const index = this.selected.indexOf(event.target.value);
                this.selected.splice(index, 1);
            }
        }
    });
</script>

<style>
    label {
        display: block;
    }
</style>

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

Tips for effectively enabling Node.js to execute its asynchronous events within my infinite while loop

Every time I execute my 'save_to_db' function at location B, it ends up failing. Below is the snippet of code that highlights the issue... //location A var i = 0; while(true) { i++; if(i == 100) { //location B save_to_d ...

What is the best way to format specific text as bold within an input text field?

I am attempting to make certain text bold within an input text field. However, I'm uncertain about how to achieve this because HTML code is not recognized inside a text field. Therefore, using <b> will not be effective. Is there a way to bold sp ...

MenuIcon Component is experiencing difficulty being rendered

I am attempting to construct an IconMenu within the AppBar Component. My project is being developed using create-react-app. This is how my code appears: index.js import React from 'react'; import ReactDOM from 'react-dom'; import &a ...

What is the best way to delete a model from a Backbone.Collection?

How can I properly remove a model from a collection in Backbone.js? var item = new Backbone.Model({ id: "01", someValue: "blabla", someOtherValue: "boa" }); var list = new Backbone.Collection([item]); list.get("01").destroy(); After calling ...

Using single variable in multiple callback functions is a recommended practice in JavaScript

In my node.js express application, I need to fetch and save responses from external URLs. I have created two arrays for this purpose - one to store the URLs and another to store the responses. var urls = ['http://example.com','http://exampl ...

Is it feasible to use PHP code within a Javascript environment?

Looking for help with integrating PHP code into a JavaScript script: var bigData = { "teams" : [], "results" : [] }; for( var i=1 ; i<16 ; i+=2 ) { bigData.teams.push(["<?php echo 1; ?>",'Team '+(i+1)]); } for( var j=1 ; j& ...

Can you provide guidance on securing a REST API using Google authentication?

I'm currently working on developing a REST API using NodeJS and Passport for a single-page JavaScript application. I am struggling to find the right approach to securing my REST API with Google OAuth. Can someone guide me on how to achieve this? Any ...

Generating a text document with the power of Vue.js

Currently, I am encountering some challenges in implementing an "export" feature for my application. The reason behind wanting to add this functionality is simple: Once users have completed certain calculations within the application, they may wish to save ...

Calculating the Surface Area of a Geometric Face in Three.js

When exporting a 3D model using the ColladaLoader, each Mesh generates a Geometry object with multiple Faces. I have successfully managed to select faces in order to change colors and textures, but now I need to calculate the area of each "Face." Faces ar ...

Tips for hovering over a link with Webdriver

Currently, for my project, I am utilizing Selenium Webdriver. Successfully automating the functionality to mouse over an image has been achieved. However, there seems to be an issue when attempting to trigger a mouse-over event on a hyperlink using the sam ...

The GIF Loader fails to animate while an AJAX request is in progress

Displaying a DIV element containing a loading GIF image while waiting for an AJAX call response. Initially, the DIV element is hidden. Upon clicking a checkbox, the loader DIV is shown, followed by the completion of the AJAX call, and then hiding the load ...

Creating a cross-platform file writer with PHP and JavaScript

My current challenge involves using buttons on an HTML page to trigger a PHP program that writes to a text file. Despite receiving a success message from my Ajax function, the file that should have been written to doesn't exist. Here's a snippet ...

Error in defining class variable within the constructor not found

Just started delving into CoffeeScript and facing a challenge. In my code snippet below, I initialize WebSocketServer with a number as the first argument and a function as the second argument. However, when the websocket receives a message, @msgHandler sud ...

Discovering documents using the outcome of a function in mongoose

Hey there, I have a scenario with two schemas known as user and driver, both containing latitude and longitude attributes. My goal is to search the database for nearby drivers based on the user's current location (latitude and longitude) using a custo ...

When located at the bottom of a page, the Div element fails to display

I need some help with my javascript code. I am working on creating a scrollable panel that closes when scrolled and reveals a #toTop div when the bottom of the page is reached. Below is the function code I have written, but for some reason, the #toTop div ...

Exploring the world of mathematics using JavaScript, adjusting the range input, and applying CSS transform with scale()

In my project, I have a container div set to a width of 794px and a range input with a maximum value of 250 and a minimum of 0. I am using CSS transform property like this: scale(1), where the scale is equivalent to 794px. The challenge arises when the br ...

Using Vue to create smooth CSS transitions for video elements, fading in and out

Within my project, there are 4 sets of videos all loading simultaneously, but only one is visible at a time. Users have the ability to switch to the next/previous videos by using arrow keys. I am interested in implementing fade in/out transitions on these ...

Connecting factors

Let me simplify what my code does: var list = { "group":{ "subgroup1":[{"name1":"Jimmy","name2":"Bob"}], "subgroup2":[{"name1":"Sarah","name2":"Nick"},{"name1":"Kevin","name2":"George"}] } } function group(group,name){ var link ...

What strategies can be employed to tackle the challenges posed by Ajax asynchronous calls?

Beginner in JavaScript - I just wanted to mention that upfront. Take a look at this straightforward example where I aim to create X number of gauges, with the value of X being retrieved from JSON using an Ajax call. <body> <div id="gServer"> ...

Navigating the elements within R Shiny: A comprehensive guide

Can anyone help me figure out how to access specific elements in my Shiny app using their HTML tags? In this particular example, I need to retrieve all h1 elements along with their respective labels and IDs. library(shiny) ui <- fluidPage( h1("Get" ...