Listen to Foundation event in Vue.js?

I am creating an application in Vue.js with a general structure:

<app>
    <filters-component></filters-component>
    <div class="off-canvas-content">
        <nav-component></nav-component>
        <div class="row card-grid">
            <card-component v-for="item in items">
                <modal-component v-if="launchModal === true"></modal-component>
            </card-component>
        </div>
    </div>
</app>

      

This allows me to display modal data in the DOM only if the data item is launchModal

set to true (after clicking the modal launch button). This works great, but I need to do the opposite when it is closed.

According to the Foundation documentation, the Reveal (modal) component should fire a named event closed.zf.reveal

when it is closed.

How can I listen to this event on the parent (map component) and then change launchModal

to false when it is called?

Thank!

+3


source to share


1 answer


Essentially this will probably work before yours modal-component

(add them to your script in Modal.vue)

methods:{
    onModalClosed(){
        this.$emit("modal-closed")
    }
},
mounted(){
    this.$el.addEventListener('closed.zf.reveal', this.onModalClosed)
},
beforeDestroy(){
    this.$el.removeEventListener('closed.zf.reveβ€Œβ€‹al', this.onModalClosed)
}

      

Or something like that, depending on which element is emitting the event. If any other element emits an event closed.zf.reveal

, you can add to it ref="modal"

and then use this.$refs.modal.addEventListener

and this.$refs.modal.removeEventListener

.

Then you could just

<modal-component v-if="launchModal === true"
                 @modal-closed="launchModal = false">
</modal-component>

      

Edit

So the problem with listening to the event is that Foundation is using jQuery to fire the event. This means you cannot listen to it with your own ( addEventListener

) methods , you must listen to it with jQuery. So the modified code above would be:



methods:{
    onModalClosed(){
        this.$emit("modal-closed")
    }
},
mounted(){
    $(this.$el).on('closed.zf.reveal', this.onModalClosed)
},
beforeDestroy(){
    $(this.$el).off('closed.zf.reveβ€Œβ€‹al', this.onModalClosed)
}

      

And this is, in essence, catching the event. The problem is that the Foundation for some reason moves the modal outside of Vue and adds it to the bottom of the document when the modal is initialized. This causes Vue to throw an error when launchModal

set to false

because the modal is no longer inside Vue, and Vue complains when it tries to remove it from the DOM.

In this case, I suggest you use v-if

inside a modal for things that are very slow to render . This will result in such a component.

Vue.component("modal", {
  props:["show"],
  template: "#modal-template",
  watch:{
    show(newVal){
      if (newVal)
        $(this.$el).foundation("open")
    }
  },
  methods:{
    onModalClosed(){
      this.$emit("modal-closed")
    }
  },
  mounted() {
    new Foundation.Reveal($(this.$el))
    $(this.$el).on("closed.zf.reveal", this.onModalClosed);
  },
  beforeDestroy() {
    $(this.$el).off("closed.zf.reveal", this.onModalClosed);
  }
});

      

And the template

<template id="modal-template">
  <div class="reveal" data-reveal>
    <div v-if="show">
      Stuff that is expensive to render
    </div>
    <button class="close-button" data-close aria-label="Close modal" type="button">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
</template>

      

And here's a working example .

+1


source







All Articles