iLyas
iLyas

Reputation: 315

Show and Hide Carousel elements on Vue JS show large Carousel on click

I have 2 divs, each of them has a carousel component and if you click on small carousel image on first div I display carousel with big images, and if you click on the rest of the app big carousel gets closed and carousel with small images gets back. All works fine until you leave the component via window.go(-1) and then come back, the code does not work. I am trying to guess why but cannot get a clue. I remove event listeners once I go to other link on a page and when I come back for some reason this.body = document.getElementById("app") get's the whole #app including 2 my divs even though for them I use event.stopPropagation and check ev.target !== this.carouselBig.
Why do the divs get substituted properly until you rerender the component? I even remove listeners and recreate new ones on mount

<template>
  <div v-if="images">
    <div
      id="carouselSmall"
      v-show="!showBigImages"
      class="block"
      style="width:400px; max-width:100%; border:1px solid #ccc; margin:10px auto; border-radius:3px;"
    >
      <el-carousel type="card" height="100px">
        <el-carousel-item v-for="item in images" :key="item.small">
          <img :src="item.small" @click="displayBigImages()">
        </el-carousel-item>
      </el-carousel>
    </div>
    <div
      id="carouselBig"
      v-show="showBigImages"
      class="block"
      style="width:100%; border:1px solid #ccc; margin:10px auto; border-radius:3px;"
    >
      <el-carousel type="card" height>
        <el-carousel-item v-for="image in images" :key="image.original">
          <img :src="image.original">
        </el-carousel-item>
      </el-carousel>
    </div>
  </div>
</template>
<script>
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

import common from "./Config";
import { Carousel, CarouselItem } from "element-ui";
Vue.use(Carousel);
Vue.use(CarouselItem);
export default {
  props: ["images"],
  data() {
    return {
      carouselBig: document.getElementById("carouselBig"),
      carouselSmall: document.getElementById("carouselSmall"),
      body: document.getElementById("app")
    };
  },
  computed: {
    showBigImages() {
      return this.$store.state.showBigImages;
    }
  },
  methods: {
    displayBigImages() {
      this.$store.commit("setshowBigImagesM", true);
    },
hideBigCarousel(destroy) {
      this.carouselBig = document.getElementById("carouselBig");
      this.carouselSmall = document.getElementById("carouselSmall");
      this.body = document.getElementById("app");

      let stopEvent = ev => {
        ev.stopPropagation();
      };

      let onBodyClick = ev => {
        if (ev.target !== this.carouselBig) {
          this.$store.commit("setshowBigImagesM", false);
        }
      };

      if (destroy) {
        this.carouselBig.removeEventListener("click", stopEvent, false);
        this.carouselSmall.removeEventListener("click", stopEvent, false);
        this.body.removeEventListener("click", onBodyClick, false);
      } else {
        this.carouselBig.addEventListener("click", stopEvent, false);
        this.carouselSmall.addEventListener("click", stopEvent, false);
        this.body.addEventListener("click", onBodyClick, false);
      }
    }
  },
  mounted() {
    window.onload = () => {
      this.hideBigCarousel();
    };
  },
  beforeDestroy() {
    this.hideBigCarousel(true);
  }
};
</script>

enter image description here

enter image description here

Upvotes: 0

Views: 1536

Answers (1)

Alex
Alex

Reputation: 1423

This is just suggestion. You need to check this, or if you give jsfiddle of something like that, I will check it.
First at all, remove from data all not data things. And use ref. v-if="images" need to change to v-show, because ref inside that div will be not work. And I remove some to clearance, you may return it in your code.

<template>
  <div v-show="images">
    <div ref="carouselSmall"
         v-show="!showBigImages"
         class="block"
    >
      <el-carousel type="card" height="100px"></el-carousel>
    </div>
    <div ref="carouselBig"
         v-show="showBigImages"
         class="block"
    >
      <el-carousel type="card" height></el-carousel>
    </div>
  </div>
</template>

<script>
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

import common from "./Config";
import { Carousel, CarouselItem } from "element-ui";
Vue.use(Carousel); // you need use them inside all components? So, replace this code to main.js
Vue.use(CarouselItem);

export default {
  props: ["images"],
  data() {
    return {
    };
  },
  computed: {
    showBigImages() {
      return this.$store.state.showBigImages;
    }
  },
  methods: {
    displayBigImages() {
      this.$store.commit("setshowBigImagesM", true);
    },
    hideBigCarousel(destroy) {
      const carouselBig = this.$refs.carouselBig;
      const carouselSmall = this.$refs.carouselSmall;
      const body = document.getElementById("app"); // maybe better use this.$root?

      let stopEvent = (ev) => {
        ev.stopPropagation();
      };

      let onBodyClick = (ev) => {
        // contains check that element inside carouselBig
        if (!carouselBig.contains(ev.target)) {
          this.$store.commit("setshowBigImagesM", false);
        }
      };

      if (destroy) {
        carouselBig.removeEventListener("click", stopEvent, false);
        carouselSmall.removeEventListener("click", stopEvent, false);
        body.removeEventListener("click", onBodyClick, false);
      } else {
        carouselBig.addEventListener("click", stopEvent, false);
        carouselSmall.addEventListener("click", stopEvent, false);
        body.addEventListener("click", onBodyClick, false);
      }
    }
  },
  mounted() {
     this.hideBigCarousel();
  },
  beforeDestroy() {
    this.hideBigCarousel(true);
  }
};
</script>

Upvotes: 1

Related Questions