LovelyAndy
LovelyAndy

Reputation: 891

Stopping an animation with an click event in Vuejs?

I have a MainMenuItem that has a bunch of static titles. There is one variable item that is for news and events and that has a horizontal ticker, scroll animation on it. This animation is happening inside of the MainMenuItem component, but the click event will be happening from the parent. The click event currently needs to stop the animation and change the font weight (can be seen in the readLink class).

Wth Vue I cannot mutate the prop type itself with something like @click="itemType = ''".

So how can I turn this ticker animation off on click?

Basically, all I would need to do is make the MainMenuItem's itemType = '' and make it the same as every other item. Do I need to make a data type? Or a click event that $emit's an event to the child/base component MainMenuItem?

If there is anymore code that is necessary please let me know!

Cheers!

MainMenuItem.vue (base component with the ticker animation )

<template>
  <q-btn align="left" dense flat class="main-menu-item" v-on="$listeners">
    <div class="flex no-wrap items-center full-width">
      <iconz v-if="iconz" :name="iconz" type="pop" color="black" class="mr-md" />
      <q-icon :name="menuIcon" />
      <div v-if="itemType === 'news'" class="_ticker">
        <div class="ellipsis _ticker-item">{{ title }}</div>
      </div>
      <div v-else>
        <div class="ellipsis">{{ title }}</div>
      </div>
      <q-icon name="keyboard_arrow_right" class="_right-side" />
    </div>
  </q-btn>
</template>

<style lang="sass" scoped>
// $
.main-menu-item
  display: block
  font-size: 15px
  position: relative
  width: 100%
  border-bottom: 1px solid #F5F5F5
  +py(10px)
  ._left-side
    color: #000000

._ticker
  font-weight: bold
  margin-left: 2em
  width: 83%
  white-space: nowrap
  overflow: hidden
  position: absolute
  &-item
    display: inline-block
    padding-left: 100%
    animation: ticker 8s linear infinite

@keyframes ticker
  to
    transform: translateX(-100%)
</style>

<script>
import { iconz } from 'vue-iconz'

export default {
  name: 'MainMenuItem',
  components: { iconz },
  props: {
    comingSoonShow: { type: Boolean, default: false },
    title: { type: String, default: 'menu' },
    subtitle: { type: String, default: '' },
    menuIcon: { type: String, default: '' },
    iconz: { type: String, default: '' },
    itemType: { type: String, default: '' },
  }
}
</script>

MainMenu.vue (just the location I am using the base component)

<template>
  <MainMenuItem
   v-for="news in newsList"
   :key="news.id"
   @click="openNews(news)"
   :title="news.title"
   itemType="news"
   :class="{ readLink: readNewsList[news.id] }"
   menuIcon="contactless"
  ></MainMenuItem>
</template>

export default {
  name: 'MainMenu',
  methods: {
    openNews(postInfo) {
      dbAuthUser().merge({ seenNewsPosts: { [postInfo.id]: true } })
      Browser.open({ url: postInfo.url, presentationStyle: 'popover' })
    }
  },

  computed: {
    readNewsList() {
      return this.authUserInfo?.seenNewsPosts || {}
    },
  }

<style lang="sass" scoped>
  .readLink
    font-weight: 500
</style>

Upvotes: 0

Views: 536

Answers (1)

Girl Codes
Girl Codes

Reputation: 368

Since it's a prop the simplest way is to emit an event that executes what you need in the parent and also bind a variable not static prop to be able to change it. example in the child :

<button @click="onClickButton">stop animation </button>

export default {
  methods: {
    onClickButton (event) {
      this.$emit('stopAnimation')
    }
  }
}

And in the parent you listen to it as so:

<MainMenuItem
   v-for="news in newsList"
   :key="news.id"
   @click="openNews(news)"
   :title="news.title"
   :itemType="itemType"
   :class="{ readLink: readNewsList[news.id] }"
   menuIcon="contactless"
v-on:stopAnimation="itemType = ''"
  ></MainMenuItem>

export default {
  data() {
        return {
            itemType: "news",
        }
    }
  }
}

Upvotes: 1

Related Questions