Using v-for with TailwindCSS animations seems to cause issues

I'm currently working on implementing a list of pop-up messages in the upper right corner of the screen. These messages should disappear when clicked and include a slide-fade transition effect.

The transition animation works fine when there is only one pop-up component, but it malfunctions when there are multiple components. I would greatly appreciate any assistance in resolving this issue. Thank you in advance.

Below is the code snippet:

popup.vue

<template>
    <Transition name="slide-fade" @click="close">
        <div class="bg-green-100 opacity-95 rounded-lg py-5 px-6 mb-3 text-green-700 inline-flex items-center text-sm" role="alert">
            <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check-circle" class="w-8 h-8 mr-2 fill-current" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                <path fill="currentColor" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"></path>
            </svg>
            {{ placeholder }}
        </div>
    </Transition>
</template>

<script>
export default {
    name: 'popupComponent',
    methods: {
        close () {
            this.$emit('close', this.arrIndex)
        }
    },
    props: {
        placeholder: String, 
        arrIndex: Number
    }
}
</script>

<style scoped>
.slide-fade-enter-active {
  transition: all 0.3s ease-out;
}

.slide-fade-leave-active {
  transition: all 0.8s cubic-bezier(.25,.59,.63,.92);
}

.slide-fade-enter-from,
.slide-fade-leave-to {
  transform: translateX(20px);
  opacity: 0;
}
</style>

App.vue:

<template>
  <div class="absolute z-10 right-0 p-2 max-w-md">
     <div class="flex flex-col gap-y-2 max-h-96 overflow-y-hidden">
        <popup v-for="(content, index) in popup_content.slice().reverse()" :key="index" @close="closePopup" :arrIndex="(popup_status.length-1) - index"  :placeholder="content"/>
     </div>  
  </div>
</template>

<script>
import popupComponent from './components/popup.vue'

export default {
  data() {
    return {
      popup_content: ['Awesome!', 'Nice!'],
    }
  },
  methods: {
    closePopup(index) {
      this.popup_content.splice(index, 1);
    }
  },
  components: {
    'popup': popupComponent
  },
  name: 'App'
}
</script>

Answer №1

It seems that the issue may arise from utilizing an index as a key.

Instead of using index as a key in your v-for loop, consider using a unique and unchanging identifier like an id. This is important especially when modifying the array as it helps Vue track changes in the DOM structure.

<popup v-for="(content, index) in popup_content.(...)" :key="content" ...>

When you delete an item from the array using the close function, the indices get rearranged causing unexpected behavior. Refer to Vue documentation for more information.

To address this, generating a unique id for each popup message upon creation is recommended. Modify your popup content structure to include ids:

popup_content: [
   {
      id: 'e5803eab...', 
      text: 'Awesome!'
    }, 
    {
      id: '8396...', 
      text: 'Nice!'
     }
],

Utilize the id as the key in your v-for loop:

<popup v-for="(popup, index) in popup_content.(...)" :key="popup.id" :placeholder="popup.text" ...>

You can still make use of the index for other functionalities within your code.

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

Exploring the syntax for navigating with JS Angular and HTML, such as when using the code snippet: ng-click="save(userForm)"

I am struggling to grasp the functionality of a specific part of this code. Despite my efforts to find tutorials, I have been unable to locate relevant information. There are two lines in particular that puzzle me: <button type="submit" class="btn btn ...

Is there a way to adjust the padding temporarily?

Important Note: Despite the misleading title of my question, it doesn't accurately reflect my actual query (sort of). Below is the code snippet in question: .one{ background-color: gray; } .two{ padding: 20px; } <div class = "one"> < ...

utilizing v-bind:href to connect a dynamic value

I am attempting to create a dynamic URL binding using the v-bind feature of vue.js. The expression I want to bind is a folder year, and I would like this expression to be rendered in the links. I am facing an issue with how I am concatenating the elements. ...

Define a new type in Typescript that is equal to another type, but with the added flexibility of having optional

I have 2 categories: category Main = { x: boolean; y: number; z: string } category MainOptions = { x?: boolean; y?: number; z?: string; } In this scenario, MainOptions is designed to include some, none, or all of the attributes that belong to ...

Securing Email and Password Data in Cypress Tests

Greetings! I trust everyone is in good spirits. My dilemma lies in the fact that I am hesitant to include email and passwords in version control. I am considering using environment variables in my cypress tests and utilizing secrets for runtime value pro ...

Using localStorage in Next.js, Redux, and TypeScript may lead to errors as it is not defined

Currently, I am encountering an issue in my project where I am receiving a ReferenceError: localStorage is not defined. The technologies I am using for this project are Nextjs, Redux, and Typescript. https://i.stack.imgur.com/6l3vs.png I have declared ...

The issue of JavaScript text not being able to be selected persists in Chrome and Internet Explorer

While the text appears fine in Firefox, it remains selectable in Chrome and Internet Explorer. Is there a way to work around this issue? The code snippet was borrowed from another post (which I cannot locate at the moment) so it may be outdated? // To pre ...

Error in AngularJS ng-repeat syntax

As a newcomer to AngularJS, I ventured into creating a Bootstrap form with a loop but encountered an error. What could be the mistake I made? <form class="form-horizontal" role="form" name="newForm" novalidate ng-controller="newFormController"> < ...

Transferring a JavaScript Value to a PHP Variable (Under Certain Constraints)

Although I have reviewed existing questions and answers related to this issue, I found that the solutions provided do not suit my specific situation. Discussing the differences between client-side JavaScript and server-side PHP, two common solutions are: ...

Shorten certain text in Vuetify

Here's an example of a basic select component in Vuetify: <v-select :items="selectablePlaces" :label="$t('placeLabel')" v-model="placeId" required ></v-select> I'm looking to apply a specific style to all selec ...

Issue with react-addons-css-transition-group and multiline TextFields in Material-UI TextField

If a TextField with multiline is nested inside a react-addons-css-transition-group, it seems to disrupt the show transition. Any suggestions on how to handle this situation effectively? Check out my code snippet here: https://codesandbox.io/s/material-dem ...

When a React component's function is passed in as a parameter, it fails to be acknowledged as a function

I've been struggling to pass a function as a parameter to a component, but it doesn't recognize the function I'm passing in as a function. Here's an important snippet from the page: const Home = () => { const nav = useNavigate() co ...

Spinning a CSS object around an axis

Trying to add a unique touch to my image rotation with CSS. While familiar with rotating around x, y, and z axis, I want to achieve a diagonal rotation this time. Wondering if there's a way to tweak the y axis for a more slanted effect on my image? ...

Setting up instagram-node-lib for managing subscriptions

I am currently working on implementing real-time updates for a specific hashtag and displaying the image on the screen. However, I am facing issues setting up my node.js server using the instagram-node-lib module. Even after running the file (node server.j ...

Boundaries on Maps: A guide to verifying addresses within a boundary

User provides address on the website. If the address falls within the defined boundary, it is marked as "Eligible". If outside the boundary, labeled as "Ineligible". Are there any existing widgets or code snippets available to achieve this functio ...

Define the starting value for Framer Motion's useCycle by taking into account the width of the screen

With the help of Framer Motion's useCycle hook, I am able to toggle the visibility of my sidebar. The desired behavior is to have the sidebar open by default on desktop (window width > 480px) and closed by default on mobile devices. To achieve thi ...

Obtain the value of a dynamically selected option

I am facing an issue with my select options where I want the input field to be automatically filled with the 'data-place' value of the selected option whenever it changes. This includes a few dynamic select options. $(function() { // Hand ...

Tips for utilizing JSON in a TypeScript file within a Node.js environment

I have been working on implementing JSON type in my Node.js application, but I am encountering some data in a scripted format. Here is the response: }, data: '\x1F\b\x00\x00\x00\x00\x00\x00\x00]PMo0\f ...

Issue with Webpack failing to bundle a custom JavaScript file

Here is the structure of my directory: Root -dist -node_modules -src --assets --css --js --scss --index.js --template.html --vendor.js package-lock.json package.json postcss.config.js tailwind.config.js common.config.js development.config.js production.co ...

Is it possible to display multiple qTips for the same target using jQuery qTip2?

I am currently utilizing the jquery qtip2 plugin to generate a mouseover tooltip. Here is the code snippet I am using: $(document).ready(function() { $("#optionalProdsImgPreview_1").qtip({ content: "<img src='http://mysite.com/myimg.jpg&ap ...