How to reactively check for a CSS class?


#1

I am using this package https://atmospherejs.com/skinnygeek1010/validate-form to do client side form validation. It will add a class “has-error” to any input with one. How would I reactively display a message based upon when/if an input has an error? I thought using a helper but it wouldn’t rerun based upon the class getting added/removed.
Any help is appreciated. Thanks!


#2

If the only feedback you got from the package is this “has-error” class, and if this “has-error” class is added to the input itself (instead of a parent div), then I see no way you can do anything. I suggest you ask the package author directly (you can post an issue on the github page), or you look for another package.


#3

I think Steve is right that you need some way to hook in to whatever function that package executes when it detects an error.

In addition to the options he suggested, you could also fork the project yourself and make the changes you need. Then submit a PR to the author and/or use a local version by putting it in your packages directory.

Update the code to allow registering callbacks via something like,

onError: function (callback) {
  this.onErrorCallbacks.push(callback);
}

Then update the part that actually detects the validation errors and have it call the callbacks in addition to whatever it normally does.

errorDetected: function (foo) {
  // ... existing code
  
  // loop through this.onErrorCallbacks and call them, passing `arguments`
}

Since javascript is dynamic you could also do something similar by dynamically modifying the package functions in your startup code. But that’s less obvious so probably less maintainable over time.


#4

The way that we handle form validation error messages is as follows.
HTML:

<template name="someForm">
  {{#if alert}}
    <div class="alert alert-danger" role="alert">
      {{alertMessge}}
    </div>
  {{/if}}  
  <form id="form">
    <input type="text" name="input"> 
  </form>
</template>

Javascript

Session.setDefault("alert", false);
Session.setDefault("alertMessage", "");
Template.someForm.helpers({
  alert:function(){
    return Session.get("alert");
  },
  alertMessage:function(){
    return Session.get("alertMessage");
  }
})

Template.someForm.events({
  'submit #form":function(){
    try {
      var input = $('input[name=input]').val();
      if(!input.length) {
        throw new Meteor.Error("no-input", "You must submit some input");
      }
      if(input.length > 140) {
        throw new Meteor.Error("input-too-long", "Your input is too long");
      }
      // Send input to server or do whatever...
    } catch(e) {
      Session.set("alert",true);
      Session.set("alertMessage", e.reason);
    }
})

The benefit of this method is that you will not have to repeat code for different error messages and the errors will always be reactive.


#5

This is exactly what I did!