DEV Community

Cover image for Toggle favourite button with vue
Larissa Avila
Larissa Avila

Posted on

Toggle favourite button with vue

What do we need?

  • A Vue project with SassCSS (I'm using my last project and modified it to use it in this example).

  • A SCSS base styles, also I added in the repo in assets folder

Step 1

In a ToggleButton.vue file we will create our button

<template>
  <label
    :for="'button-'+id"
    :class="{ active: isActive }"
    class="toggle__button"
    @change="OnChange"
  >
    <span v-if="isActive" class="toggle__label">{{ enableText }}</span>
    <span v-if="!isActive" class="toggle__label">{{ disabledText }}</span>

    <input
      type="checkbox"
      :disabled="disabled"
      :id="'button-'+id"
      v-model="checkedValue"
    />
    <span class="toggle__switch"></span>
  </label>
</template>

<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    },

    labelEnableText: {
      type: String,
      default: "On"
    },

    labelDisableText: {
      type: String,
      default: "Off"
    },

    id: {
      type: String,
      default: "primary"
    },

    defaultState: {
      type: Boolean,
      default: false
    },

    item: Object
  },

  data() {
    return {
      currentState: this.defaultState
    };
  },

  watch: {
    defaultState: function defaultState() {
      this.currentState = Boolean(this.defaultState);
    }
  },

  methods: {
    OnChange() {
      this.$emit("OnChange");
    }
  },

  computed: {
    isActive() {
      return this.currentState;
    },

    enableText() {
      return this.labelEnableText;
    },

    disabledText() {
      return this.labelDisableText;
    },

    checkedValue: {
      get() {
        return this.currentState;
      },

      set(newValue) {
        this.currentState = newValue;
        this.$emit("change", newValue);
      },
    },
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

Step 2

In a CardItem.vue file we will create a card component

<template>
  <div class="carditem">
    <div class="carditem__image">
      <img :src="pathBase+'futurama'+character.id+'.jpg'" />
    </div>
    <div class="carditem__info">
      <strong class="carditem__title">{{ character.name.first }} {{ character.name.last }}</strong>
      <span>{{ character.occupation }}</span>
      <span>{{ character.species }}</span>
      <slot></slot>
    </div>
  </div>
</template>
<script>
export default {
  name: "CardItem",

  props: {
    character: {
      type: Object,
    },
    index: Number,
    showPage: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      pathBase: "https://res.cloudinary.com/lariicsa/image/upload/v1602727260/futurama/",
      charImages: [
        { name: "Philip", url: "" },
        { name: "Turanga", url: "" },
        { name: "Bender", url: "futurama4_pxj04y.jpg" },
        { name: "Hubert", url: "" },
        { name: "Amy", url: "" },
        { name: "Hermes", url: "" },
        { name: "Carol", url: "" },
        { name: "John", url: "" },
        { name: "Zapp", url: "" },
        { name: "Scruffy", url: "" },
        { name: "Cubert", url: "" },
        { name: "Kif", url: "" },
        { name: "Dwight", url: "" },
        { name: "LaBarbara", url: "" },
      ],
    };
  },

  mounted() {
    this.index;
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Step 3

In App.vue file, our main view, we will integrate our components

<template>
  <div id="app" class="space">
    <div class="container">
      <div class="row center">
        <h1>Futurama</h1>
      </div>
      <div class="row center">
        <div class="row between">
          <CardItem
            v-for="(character, index) in characters"
            :character="character"
            :key="index"
            :index="index"
          >
            <ToggleButton
              :item="character"
              :defaultState="false"
              :id="index.toString()"
              @OnChange="AddTofavs()"
            />
          </CardItem>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import store from "@/fakeStore/characters";
import CardItem from "@/components/CardItem";
import ToggleButton from "@/components/ToggleButton";
export default {
  name: "App",
  components: {
    CardItem,
    ToggleButton
  },

  data() {
    return {
      characters: store.characters
    };
  },

  methods: {
    AddTofavs() {
      this.$emit("AddTofavs")
    }
  }
};
</script>
Enter fullscreen mode Exit fullscreen mode

We are using Watch Vue property to listen the checkbox state.
Also we can use this component with store actions.

Here you can check the Demo Link

Here is the repo

Happy wapi Coding! :D

Top comments (0)