[Vuejs]-Vue.js 3 optional v-scroll-to

0๐Ÿ‘

โœ…

As v-scroll-to cannot be bound to v-bind, I found a little work around that actually solve my issue and avoid to duplicate the code twice. I bind the @click to a method that inspect the url value and $scollTo if needed, and it solve my problem.

<template>
  <div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
    <component
      :is="buttonComponent"
      v-for="(button, index) in buttons"
      :key="button.label"
      :label="button.label"
      v-bind="type(button.type)"
      @click="scrollTo(button.url)"
      :style="`margin-left: ${index === 0 ? '' : space};`"
    />
  </div>
</template>

<script>
export default {
  name: "ButtonLayout",
  components: {},
  props: {
    button: String,
    margin: String,
    align: String,
    space: String,
    buttons: Array
  },
  methods: {
    type(type) {
      return type ? { type } : {}
    },
    scrollTo(url) {
      if (url) this.$scrollTo(url)
    }
  },
  computed: {
    buttonComponent() {
      return () => import(`./button/${this.button}`);
    }
  }
};
</script>

0๐Ÿ‘

You can pass an object to v-bind and it will create html attributes based on the keys of the object.

Something like this should work

<component
      :is="buttonComponent"
      v-for="(button, index) in buttons"
      :key="button.label"
      :label="button.label"
      v-bind="{[button.url ? 'v-scroll-to' : 'type' ] : (button.url || button.type} }"
      :style="`margin-left: ${index === 0 ? '' : space};`" />

Or you could declare a new method that returns the desired object

methods: {
  buttonDirective (button) {
   if (button.url) {
     return {
       'v-scroll-to': button.url
     }
   } else {
     return {
       'type': button.type
     }
   }
  }
}

and then call it in component

<component
      :is="buttonComponent"
      v-for="(button, index) in buttons"
      :key="button.label"
      :label="button.label"
      v-bind="buttonDirective(button)"
      :style="`margin-left: ${index === 0 ? '' : space};`" />

Leave a comment