Vuetify 3.4/Vue 3.3 radiogroup :rules example?

58 Views Asked by At

Pretty basic question. I'm looking for an example of a vuetify 3.4/ vue 3.3 radiogroup with validation rules. Ideally using the composition api.

This is a shorted version based of the playground example:

<template>
  <v-form :model="valid">
    <v-text-field
      v-model="textfield"
      :rules="requiredValue"
      label="First name"
      required
    >
    </v-text-field>

    <v-radio-group :model="rbg" label="Pick a number" :rules="requiredValue" required>
      <v-radio label="Radio One" value="one"></v-radio>
      <v-radio label="Radio Two" value="two"></v-radio>
      <v-radio label="Radio Three" value="three"></v-radio>
    </v-radio-group>
    <button>I'm just here to have a tabbable element</button>
  </v-form>
</template>

<script>
  export default {
    data: () => ({
      valid: false,
      textfield: '',
      rbg: '',
      requiredValue: [
        value => {
          if (value) {
            return true
          }
          return 'This is a required field'
        },
      ],
    }),
  }
</script>

If you tab through the input field and leave it blank, you get the error message. But not if you tab through the radiogroup. I tried forcing a validation by adding validate-on="blur" to the v-radio-group, but that didn't work.

You can do it if you ignore most of vuetify's features. I put @blur on each of the radio buttons and run the validation on the blur. I do use vuetify's :error-messages and set it to a reference variable. The validation function sets the message to either a null (valid) or a string for the error message. This works, but seems like I should be able to use the :rules and validate-on with the v-radio-group since they are listed in the api for it.

Any good, working examples of this?

1

There are 1 best solutions below

0
Bob Ramsey On

According to the documentation at https://vuetifyjs.com/en/api/v-radio-group/#props a v-radio-group have validate-on='blur' to run validation after the user has entered and left the group. However, in my experience and Moritz Ringler's comment above confirms, this is just not the case with "vue": ^3.3.4" and "vuetify": "^3.4.4". So if you are attempting to validate a radio-group after a keyboard user focuses and blurs out of it (tab or shift+tab), you are simply out of luck. However, I have a workaround and it might even have less overhead.

In my template:

<v-radio-group
  v-model="myAnswer"
  :error-messages="myAnswerErrMsg"
>
  <v-radio
    value="y"
    label="Yes"
    @blur="myAnswerTouched=true;checkAnswer()"
  >
  </v-radio>
  <v-radio
    value="n"
    label="No"
    @blur="myAnswerTouched=true;checkAnswer()"
  >
  </v-radio>
  <v-radio
    value="m"
    label="Maybe"
    @blur="myAnswerTouched=true;checkAnswer()"
  >
  </v-radio>
</v-radio-group>

In my setup script, composition api I have:

const myAnswer = ref('');
const myAnswerTouched = ref(false);
const mymyAnswerErrMsg: Ref<string | null> = ref(null);

function checkAnswer(): void {
    if ( ['y', 'n'].includes( myAnswer ) ) {
      myAnswerErrMsg = myAnswerTouched ? 'Please answer the question' : null;
      return;
    } else if (myAnswer === 'm' && myAnswerTouched) {
      myAnswerErrMsg = 'Whaddaya mean, maybe?';
      return;
    } 
    myAnswerErrMsg = myAnswerTouched ? null : 'Please answer the question';
}

The basic idea is to have a ref variable that tracks whether or not the user has blurred through at least one of the radio options. I put it on all of them because it doesn't really matter, but I think you can get away with just putting it on the first and last v-radio elements since you can't tab into the middle of an unanswered radio group.

Also when the user blurs out of the answer it runs a checkAnswer function, which sets the value of the myAnswerErrMsg ref variable. If the conditions are not met, then myAnswerErrMsg is set to the error message. If the conditions are met, then it is set to null. If the :error-messages property on the v-radio-group is not null, then the message displays.

You might think about just setting :error-messages to a function's return value, but without additional code, that won't be reactive and only runs the first time the page is rendered. It seemed simpler to just add another ref variable then to make the function itself reactive.

The above is pseudocode. It probably works, but since I was simplifying code I may have some typos.

If vuetify fixes the documentation or the component, ymmv in the future. Those are the versions that were broken for me. Vuetify playground example