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

Top comments (0)

Why You Need to Study Javascript Fundamentals

The harsh reality for JS Developers: If you don't study the fundamentals, you'll be just another “Coder”. Top learnings on how to get to the mid/senior level faster as a JavaScript developer by Dragos Nedelcu.