VInput rules and requirements using extend

I’m using Vue+Vuetify, and I need to rework a custom selector component.

The current code looks like this:

<template>
  <v-autocomplete
    :id="id"
    v-model="internalValue"
    :clearable="clearable"
    :disabled="disabled"
    :hide-details="hideDetails"
    :label="label"
    :readonly="readonly"
    :required="required"
    :rules="rules"
    :items="items"
    item-value="id"
    item-text="name"
    no-data-text="No data"
  />
</template>

<script>
export default {
  name: 'MyCustomSelector',
  props: {
    value: {
      type: String,
      default: null,
    },
    label: {
      type: String,
      default: '',
    },
    id: {
      type: String,
      default: null,
    },
    required: Boolean,
    clearable: Boolean,
    hideDetails: Boolean,
    disabled: Boolean,
    readonly: Boolean,
  },
  data() {
    return {
      items: [],
      rules: [
        (value) => {
          if (this.required) {
            return !!value || 'This field is empty'
          } else {
            return true
          }
        },
      ],
    }
  },
  apollo: {
    // apollo logic
      ...
      this.items = loadedItems
      ...
  },
  computed: {
    internalValue: {
      get() {
        return this.value
      },
      set(newVal) {
        this.$emit('input', newVal)
      },
    },
  },
}
</script>

As you can see, almost all of the code is just a props pass. So I decided to change the code to:

<script>
import VAutocomplete from 'vuetify/lib/components/VAutocomplete'

export default VAutocomplete.extend({
  name: 'MyCustomSelector',
  props: {
    itemText: {
      type: String,
      default: 'name',
    },
    itemValue: {
      type: String,
      default: 'id',
    },
    rules: {
      type: Array,
      default: () => [
        (value) => {
          if (this.required) {
            return !!value || 'This field is empty'
          } else {
            return true
          }
        },
      ],
    },
    noDataText: {
      type: String,
      default: 'No data',
    },
  },
  apollo: {
    // apollo logic
      ...
      this.cachedItems = loadedItems
      ...
  },
})
</script>

Everything is fine, but there is a small problem – prop rules cannot work the way I want because this.required is unknown.

This prop is taken from the Validatable mixin, in which the value from the field is simply substituted in turn to each of the rules.

The question is, how can I make code where the rule depends on the state of the required field?

Answer

You have to use a traditional function instead of the arrow function, to get prop’s data

 rules: {
  type: Array,
  // change to the traditional function
  default: function () {
    return [
      (value) => {
        if (this.required) {
          return !!value || "This field is empty";
        } else {
          return true;
        }
      },
    ];
  },
},