Search code examples
vue.jspopupvuejs3primevue

Popup on top of each other VUEJS3


I want to put several Buttons, each one opening a different Popup. A Popup would print data concerning its Button.

I have a Popup.vue component :

<template>
    <div class="popup">
        <div class="popup-inner">
            <slot />
            <Button class="popup-close" @click="TogglePopup()">
                Close
            </Button>
        </div>
    </div>
</template>

<script>
export default {
    props: ['TogglePopup']
}
</script>

And in another .vue I call it like that :

    <template>
        <div v-for="infoItem in data" :key="infoItem.name"> // loop to create several buttons
    
           <Button
              icon="pi pi-eye"
              @click="() => TogglePopup('buttonTriggerDetail')">
           </Button>
    
           <Popup
             v-if="popupTriggers.buttonTriggerDetail"
             :TogglePopup="() => TogglePopup('buttonTriggerDetail')"
           >
           {{ infoItem.control }}
           </Popup>
    </div>
    
    </template>

<script>

import ...

export default {
  computed: {
    data() {
      return this.$store.state.data;
    },
  },
  mounted() {
    this.$store.dispatch("getData");
  },

  setup() {
    const popupTriggers = ref({
      buttonTriggerDetail: false
    });
    const TogglePopup = (trigger) => {
      popupTriggers.value[trigger] = !popupTriggers.value[trigger];
    };

    return {
      Popup,
      TogglePopup,
      popupTriggers,
    };
  },
};
</script>

So it prints several Button but when I click on one, it don't open the Popup with the data of this Button, it always prints the data of the last Button. I think in reality it places all the pop up on top of each others.

How can I do to open only the good Popup with the good data ? Thanks


Solution

  • The mistake is that you are rendering 3 popups when you need only one with certain props. Think of your popups as of tabs: let popup be rendered by clicking on certain button and pass in props you need, for example:

    <template>
     <div v-for="infoItem in data" :key="infoItem.name"> // loop to create several buttons
      <Button
       icon="pi pi-eye"
       @click="clickHandler">
      </Button> 
     </div>
     <Popup
       v-if="popupTriggered"
       :TogglePopup="() => TogglePopup('buttonTriggerDetail')"
     >
       {{ data[currentActiveItem].control }}
     </Popup>
    </template>
    
    <script>
    
    import ...
    
    export default {
      data () {
        currentActiveItem: 0,
        popupTriggered: false
      },
      methods: {
        clickHandler (index) {
          this.popupTriggered = true
          this.currentActiveItem = index
        }
      }
    ... // other component data
    };
    </script>
    
    

    I wrote my example in Vue 2 style because I haven't worked with Composition API yet but I hope you got the idea.