Skip to content

Instantly share code, notes, and snippets.

@bseib
Last active October 27, 2018 02:08
Show Gist options
  • Save bseib/30570a7c0d5e5a1499fa57ce09fa2f2b to your computer and use it in GitHub Desktop.
Save bseib/30570a7c0d5e5a1499fa57ce09fa2f2b to your computer and use it in GitHub Desktop.
VueJS directive to inject 'is-invalid' class on element based on a value
// Register a global custom directive called `v-invalid`
Vue.directive('invalid', (function() {
var setInvalidClass = function(el, isInvalid) {
var isActWhenUntouched = el['_isActWhenUntouched'];
var isTouched = el['_isTouched'];
if ( isActWhenUntouched || isTouched ) {
if ( isInvalid ) {
el.classList.add('is-invalid');
}
else {
el.classList.remove('is-invalid');
}
}
};
var inputListener = function(e) {
//console.log("touch happened.");
e.target['_isTouched'] = true;
e.target.classList.add('is-touched');
};
return {
inserted: function (el, binding) {
//console.log("inserted-binding-value="+binding.value);
var isActWhenUntouched = !! binding.modifiers.untouched;
el['_isActWhenUntouched'] = isActWhenUntouched;
setInvalidClass(el, binding.value);
el.addEventListener('input', inputListener);
},
componentUpdated: function(el, binding) {
//console.log("componentUpdated-binding-value="+binding.value);
setInvalidClass(el, binding.value);
},
unbind: function(el, binding) {
//console.log("ubind-binding-value="+binding.value);
el.removeEventListener('input', inputListener);
},
}
})());
@bseib
Copy link
Author

bseib commented Oct 27, 2018

This is intended to be used with Bootstrap, where .is-invalid class will mark an input field invalid.

<div class="form-group">
  <label for="person-name-input">Your name</label>
  <input type="text" class="form-control" id="person-name-input" v-model="personName" v-invalid="!isValidPersonName">
  <small id="personNameHelp" class="form-text text-muted ml-1">Valid names must be at least 2 characters long.</small>
</div>
    new Vue({
      el : '#some-page',
      
      data : {
        personName: "",
      },
      
      computed : {
        isValidName: function() {
          return this.personName.length >= 2;
        },
      }.
    });

The element will not be given the is-invalid class until it has been "touched", i.e., received an input event. If you wish to apply the is-invalid class immediately, then use the untouched modifier on the directive:

<div class="form-group">
  <label for="person-name-input">Your name</label>
  <input type="text" class="form-control" id="person-name-input" v-model="personName" v-invalid.untouched="!isValidPersonName">
  <small id="personNameHelp" class="form-text text-muted ml-1">Valid names must be at least 2 characters long.</small>
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment