Toggle favourite button with vue
Tags: vue, scss, watchers
Published: 2021-01-15 01:58:39

## What do we need?

- A Vue project with SassCSS (I'm using [my last project](https://dev.to/lariicsa/vue-responsive-infinite-scroll-component-3oji) 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

```vue
<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>
```

**Step 2**

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

```vue
<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>
```


**Step 3**

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

```vue 
<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>
```

> 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]("https://toggle-button.herokuapp.com/")

[Here is the repo]("https://github.com/Lariicsa/toggle-button/tree/master")

Happy wapi Coding! :D