wcyankees424
wcyankees424

Reputation: 2654

Can't get Bootstrap-vue form validation working

I am using Vue CLI and Bootstrap and am having trouble with the form validation currently when the page loads all the input fields load as invalid. I can see why this is happening because the input fields are getting a class of is-invalid. I have fixed this by passing the state prop a value of null when it is false. It does not seem like the default behavior should be to run the validation when the page loads but maybe it is. I believe I have everything set up correctly as far as structure and proper classes I followed the bootstrap-vue docs.

My Code

<b-form
            @submit.prevent="addReview"
            name="review-form"
            class="needs-validation"
            novalidate
          >
            <div class="name">
              <label class="sr-only" for="form-input-name">Name</label>
              <b-input
                id="form-input-name"
                class="form-inputs mb-2 mr-sm-2 mb-sm-0"
                v-model="name"
                placeholder="Name"
                required
                :state="isEmpty(this.name) ? true : null" <---- My problem is here
              ></b-input>
              ...
          </b-form>

My problem is I need 3 results from this ternary which obviously isn't possible. I need null on load to remove the error messages then false to display error on validation and true to display valid input. I have been struggling with this for days so any help with any aspect of this setup would be greatly appreciated if you want more code let me know. The submit button adds a class of was-validated which does display any error messages that are associated with empty inputs but doesn't validate the inputs.

Question
How do I validate inputs while still keeping form error messages hidden on load.

Upvotes: 4

Views: 10291

Answers (1)

caulfield
caulfield

Reputation: 56

You aren't bound to just using a ternary statement in the :state prop - you can hook :state up to a computed property directly, which will achieve three things (this is similar to what is shown in the documentation):

  1. We can have more than two conditions, breaking out of the limitations of the ternary statement.
  2. The computed property will analyze user input on the fly, ensuring real-time validation of the form input.
  3. Our template code will be cleaner and more readable (important).

I'm working loosely off of your example, but something like the following should solve your issue:

<template>
  <div id="app">
    <img width="25%" src="./assets/logo.png" style="margin-bottom: 15px;">
    <b-form>
      <div class="name">
        <label class="sr-only" for="form-input- name">Name</label>
        <b-input v-model="name" id="form-input-name" :state="isNameStateValid"></b-input>
      </div>
    </b-form>
  </div>
</template>

<script>
  export default {
    name: "App",
    data() {
      return {
        name: ""
      };
    },
    methods: {
      isValid() {
        return this.name.length > 3 ? true : false; //your validation criteria goes here
      }
    },
    computed: {
      isNameStateValid() {
        if (this.name) {
          return this.isValid(this.name);
        }
        return null;
      }
    }
  };
</script>

In the above, you would have a method that would check for your specific validation criteria (isValid, isEmpty, etc.).

Our new computed property, isNameStateEmpty, will use that method's return value, returning false for a validation failure (triggering BootstrapVue's failed validation state), true for a validation pass, or null in the event that this.name does not have a current value (examples being a fresh page load, or a user clearing the input field, making it blank).

See a working Codesandbox of this behavior here.

Because the input's v-model (v-bind:value and @change) is set to our "name" data property, every character change within the input field will reactively update our data property (this.name).

Because our isNameStateValid computed property has a dependency of this.name, it will reevaluate on every change of the this.name data property - ensuring real-time validation using BootstrapVue's validation state.

Hopefully that helps.

Upvotes: 3

Related Questions