DEV Community

DanCharousek
DanCharousek

Posted on

How to make Vue's (v2) v-model or syncable props optional?

Long story short

Use computed with getter and setter that conditionally use either passed property or internal data.

Component definition:

<!-- FooModal.vue -->
<template>
  <div v-show="syncShow">
    Lorem ipsum dolor sit, amet consectetur adipisicing elit.    
    <button @click="syncShow = false">
      Close self
    </button>
  </div>
</template>

<script>
export default {
  props: {
    // property that controls the visibility of the modal (if used)
    show: {
      type: Boolean,
      required: false,
      default: null
    }
  },

  data: () => ({
    // internal state for cases where prop is not defined
    intShow: true
  }),

  computed: {
    // proxy computed that uses either internal state
    // or passed property (if present).
    syncShow: {
      get () {
        return this.show === null
          ? this.intShow
          : this.show;
      },

      set (val) {
        if (this.show === null) {
          this.intShow = val;
        } else {
          this.$emit('update:show', val);
        }
      }
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

And then, it's usage:

<!-- App.vue -->
<template>
  <div id="app">
    <!--
      You can control the visibility from the parent scope.
    -->
    <FooModal :show.sync="showFoo" />

    <!--
      Or you can let the component handle it.
    -->
    <FooModal />
  </div>
</template>

<script>
import FooModal from './components/FooModal.vue'

export default {
  components: {
    FooModal
  },
  data: () => ({
    showFoo: true
  })
}
</script>
Enter fullscreen mode Exit fullscreen mode

Let me know if you use any other way to achieve the same.

Dan

Oldest comments (0)