Navigation

Bootstrap Form Validation Done Right in AngularJS

Using AngularJS with the Bootstrap CSS framework makes it trivially simple to implement form validation on your site. You just need to use the ngClass directive to apply the ‘has-error’ class when the input value is invalid. Here’s an example:

  <form name="userForm">
    <div class="form-group" ng-class="{ 'has-error': userForm.email.$invalid }" >
      <input type="email" class="form-control" name="email" ng-model="user.email" required />
    </div>
  </form>

What is not trivially simple is to have your form validation actually provide a good user experience (e.g. the input box above is highlighted invalid before the user even has a chance to enter anything).

So I want to share the process I went through to create a custom Angular directive that provides a great user experience. Others have also written about creating better experiences for form validations, but I have still found them lacking.

The directive itself is called showErrors, and it can be downloaded through Bower with angular-bootstrap-show-errors. The code is located on Github at https://github.com/paulyoder/angular-bootstrap-show-errors

First Attempt

As I already mentioned, most people’s first attempt at form validation with AngularJS involves the ngClass directive coupled with the $invalid property on the form control. It looks something like this:

<div class="form-group" ng-class="{ 'has-error': userForm.email.$invalid }">

And here is a complete example along with a preview of how it behaves.

<form name="userForm">
  <div class="form-group" ng-class="{ 'has-error': userForm.name.$invalid }">
    <input type="text" class="form-control" name="name" ng-model="user.name" required>
  </div>
  <div class="form-group" ng-class="{ 'has-error': userForm.email.$invalid }">
    <input type="email" class="form-control" name="email" ng-model="user.email" required>
  </div>
</form>

This does the basic job of displaying which fields are invalid, but as a user it’s really annoying being shown which fields are invalid before you even have the chance to fill out the form.

Dirty Checking

Fortunately we can use the $dirty flag that AngularJS provides to wait until the user enters information before showing the invalid entries. So we’ll update the ngClass directive with the following logic.

<div ng-class="{ 'has-error': userForm.email.$invalid && userForm.email.$dirty }" class="form-group">

This works great for the Name text box, but now when the user starts typing in the email, it shows an error after the user enters the first letter. This is because a single letter is not a valid email address, but the $dirty flag is true because the user has entered text. What we want is to wait until the user has finished entering the full email address before we perform the validation.

Waiting to validate the input box until after the user has finished entering the full email address isn’t possible with just the ngClass directive, so we’ll need to create a custom directive to help us.

After Finished Editing

It’s pretty easy to create a directive that will add the ‘has-error’ class after the user leaves the text box.

angular.module('app', []).
  directive('showErrors', function() {
    return {
      restrict: 'A',
      link: function(scope, el) {
        el.bind('blur', function() {
          var valid = // is valid logic
          el.toggleClass('has-error', valid);
        });
      }
    }
  });

We still have a couple issues we need to overcome in this directive though. First, the ‘has-error’ class for Bootstrap is not added to the text box itself, but rather to the surrounding div with the ‘form-group’ class. And second, the directive needs to know if the text box has invalid input.

This means a couple things for the directive. It needs to be placed on the div with the ‘form-group’ class, and it needs access to the form controller so it knows if the text box is invalid or not.

So our html now looks like this:

  <form name="userForm">
    <div class="form-group" show-errors>
      <input type="text" class="form-control" name="name" ng-model="user.name" required />
    </div>
    <div class="form-group" show-errors>
      <input type="email" class="form-control" name="email" ng-model="user.email" required />
    </div>
  </form>

And our directive looks like this:

angular.module('app', []).
  directive('showErrors', function() {
    return {
      restrict: 'A',
      require:  '^form',
      link: function (scope, el, attrs, formCtrl) {
        // find the text box element, which has the 'name' attribute
        var inputEl   = el[0].querySelector("[name]");
        // convert the native text box element to an angular element
        var inputNgEl = angular.element(inputEl);
        // get the name on the text box so we know the property to check
        // on the form controller
        var inputName = inputNgEl.attr('name');

        // only apply the has-error class after the user leaves the text box
        inputNgEl.bind('blur', function() {
          el.toggleClass('has-error', formCtrl[inputName].$invalid);
        })
      }
    }
  });

Now this provides a much better user experience since the validation errors aren’t shown until after the user has finished entering data into the form.

Manually Checking for Errors

An additional scenario we need to account for is when the user tries to save the form before entering information into all the form fields. The user doesn’t know the form is invalid yet because they haven’t entered any information. Which means our directive won’t show the invalid fields.

A common practice for this situation is to disable the Submit/Save button on the form until the form is valid.

<button class="btn btn-primary" ng-disabled="userForm.$invalid">Save</button>

I highly discourage this practice though, because it provides a horrible experience for the user. They see that the save button is disabled, but they have no idea why. So you’re forcing the user to think and try to figure out why they can’t save the form. Apps should never force the user to try to figure out why they can’t do some action. The app should always tell the user why they can’t perform an action.

So a better experience is to always have the save button enabled. Then if the user tries to save the form before it’s valid, we can show the invalid fields. Let’s update the directive to allow for this.

Basically we’ll need the ability to force the directive to check the validity even if the user hasn’t entered information yet. To do this, the controller broadcasts the ‘show-errors-check-validity’ event. The showErrors directive subscribes to this event and will check the validity when it is fired.

Here’s an example of how that looks:

// inside the directive's link function from the previous example
scope.$on('show-errors-check-validity', function() {
  el.toggleClass('has-error', formCtrl[inputName].$invalid);
});

And we’ll have the Add User button call the save() function on the controller.

<button class="btn btn-primary" ng-click="save()">Add User</button>

And the save function will broadcast the show-errors-check-validity event which will cause the directive to show the fields with validation errors.

// in the controller
$scope.save = function() {
  $scope.$broadcast('show-errors-check-validity');

  if ($scope.userForm.$invalid) { return; }
  // code to add the user
}

This is looking pretty good now. The only thing left to implement is the reset functionality.

Reset

The reset link currently clears out any input in the textboxes, but it doesn’t hide any form validation errors that were previously being shown. You can see what I mean by entering an invalid email and then click the reset link. The email texbox is cleared, but it still shows there is an error.

To account for this, we’ll do something similar to what we did for manually checking the validity. The controller will broadcast the show-errors-reset event and the directive will remove the has-error class from the DOM.

// inside the directive's link function from the previous example
scope.$on('show-errors-reset', function() {
  $timeout(function() {
    el.removeClass('has-error');
  }, 0, false);
});

You probably noticed the $timeout function was used to remove the ‘has-error’ class. This is because we need to wait until the current digest cycle has finished before removing the class. Else there’s a race condition that will keep the class from being removed.

Showing Validation Messages

And to put the finishing touch on, let’s show the user an error message that explains why the field is invalid. Fortunately we don’t have to change the directive to do this. We just need to add the error message and a few lines of CSS.

In the html we’ll add a paragraph with a ‘help-block’ class and only show it if the property has an error.

  <form name="userForm">
    <div class="form-group" show-errors>
      <input type="text" class="form-control" name="name" ng-model="user.name" required />
      <p class="help-block" ng-if="userForm.name.$error.required">The user's name is required</p>
    </div>
    <div class="form-group" show-errors>
      <input type="email" class="form-control" name="email" ng-model="user.email" required />
      <p class="help-block" ng-if="userForm.email.$error.required">The user's email is required</p>
      <p class="help-block" ng-if="userForm.email.$error.email">The email address is invalid</p>
    </div>
  </form>

And the CSS we add will hide the error message unless the has-error class is present.

.form-group .help-block {
  display: none;
}

.form-group.has-error .help-block {
  display: block;
}

Showing Valid Entries

I also recently updated the directive to show the user valid entries by applying the show-success class on valid input values. The demo below shows how the Name field will turn green after you enter a name and tab out of it.

There’s two ways to configure the directive to show valid entries. You can configure it on every input box by passing in the `{showSuccess: true}’ option.

<div class='form-group' show-errors='{ showSuccess: true }'>
  <input type='text' name='firstName' ng-model='firstName' class='form-control' required />
</div>

Or you can configure it globally by using the showErrorsConfigProvider

app = angular.module('yourApp', ['ui.bootstrap.showErrors']);
app.config(['showErrorsConfigProvider', function(showErrorsConfigProvider) {
  showErrorsConfigProvider.showSuccess(true);
});

Conclusion

And now we have a custom AngularJS directive that provides a great user experience for form validation errors. And the great part is how easy it is to add this to any form.

Feel free to use this directive in your project, and let me know of any further optimizations you make to the directive as well.

3 Takeaways from MicroConf 2014

MicroConf 2014 just finished up, and as I’m getting ready to fly back home this morning, I am taking the advice of Rob and Mike, and recording 3 actionable takeaways that I can apply to my self-funded business, DonorElf.

The first takeaway is to teach everything I know. Nathan Barry hit on this topic the second day in his presentation. I’ve known for a long time that people who teach online have grown huge audiences and as a result, have been able to sell more of their products. And I have had a desire to start teaching more through blogs and giving presentations, but I really don’t enjoy the actual process of writing blog posts or preparing to give a presentation. Teaching has kind of been like eating brussels sprouts for me. I know it’s good for me, but I don’t it. I know teaching will be a great benefit for me, but I don’t like putting the time in to teach. One reason I don’t enjoy the process is because I’m slow at it. I’m a really fast developer and it doesn’t take me long to crank out some code. But writing a blog posts takes a long time, and I often get stuck in what I should say. Or I write an outline of what I want to say, but then it’s difficult for me to expand on the points. Anyways, I’m going to start sucking it up and eating my brussels sprouts because I know it’s good for me and in the long run I know I will start enjoying it.

The second takeaway is to find my product’s message, or unique selling proposition (USP). Jesse Mecham spoke to this in his presentation where he shared how his product, YNAB, has grown through the years. YNAB is budgeting software for individuals, and there’s a lot of competition in that marketplace. When Jesse found the message for YNAB and started teaching it, his sales started to take off. And the message was simple: give every dollar a job, save for a rainy day, roll with the punches, live on last month’s income. The message became the top priority. The software was second to the message. But as people came to understand the message, they naturally wanted to buy the software. I know there is ample opportunity for me to find DonorElf’s message.

And the third takeaway is to embrace the importance of rest. Both Sherry Walling and Mike Tabor hit on this in their presentations. I’ve been working on DonorElf for 3 1/2 years on the side of a full time job and having a wife and 2 kids. Itt can get exhausting, and I have been burnt out many times. I have known the importance of rest, but sometimes I get frustrated when I rest because that means stuff isn’t getting done with DonorElf. But Sherry mentioned that many founders have ‘collateral damage’ in their lives with strained relationships with their spouse and friends. And the last thing I want to do is be an absent spouse and father to my wife and kids. They are the reason I’m doing what I’m doing, and I have failed if I become a workaholic and not present in their lives. So I’m not going to feel bad or frustrated when I do take a timeout and rest.

This was my first year of attending MicroConf, and I would recommend it as the most important conference to attend for any self-funded company. The presentations were amazing and I came away over 30 pages of notes with great ideas on how I can improve DonorElf. But the most important takeaway I got out of MicroConf was the new relationships I built with the other attendees. It was great hearing other’s stories, and I look forward to staying in touch with them. And I’m definitely looking forward to coming back next year.

AngularJS: Thousands Separators in Input Boxes

AngularJS makes it easy to add thousands separators when displaying numbers on a web page. All you need to use is the number filter provided by the AngularJS framework. Here’s a quick example:

<span>{{company.employeeCount | number }}</span>

But there is not an easy way to add thousands separators to input boxes. The number filter does not work on input boxes, so we can’t use it to help us. For example, the following markup does not work in AngularJS:

<!-- does not work -->
<input type="text" ng-model="company.employeeCount | number" />

So we’re left to create a custom directive to add commas for thousands separators in text boxes.

Before we start writing the directive, we need to step back and consider the user experience we want the directive to provide. We don’t always want to show the thousands separators in the text box. For instance, when the text box has focus and the user is editing the number, the thousand separators should not show. And when the user is done editing and the text box loses focus, we want to re-add the thousands separators.

To provide this user experience, I created the FCSA Number directive. All you need to do is add fcsa-number as an attribute on the input text box, and the directive will take care of adding commas for thousands separators, and it will remove the commas when the text box receives focus.

Here’s a quick demo of the directive (It also provides optional number validations too)

If you want to use it on your site, just follow the installation instructions in the Readme file on the project’s Github site.

Getting started with RoundHouse on an existing database

My team recently decided to start using RoundHouse to automate our database deployments, and I tried searching for documentation specific to using RoundHouse on a legacy database, but I didn’t find much. So I’m sharing here what I learned while setting up RoundHouse to be used on an existing database.

I’m going to keep this post focused specifically on the steps needed to get up and running with RoundHouse on a legacy database. I won’t go into much detail on all the different features RoundHouse has to offer because there’s plenty of other resources for that.

Many RoundHouse tutorials I found recommend creating a separate console project in Visual Studio that executes RoundHouse for the Db deployments. I prefer to just use the command line app provided by RoundHouse instead.

Here are the steps I came up with. I’m not an expert in RoundHouse, so there might be a better way, but this worked for me.

Create the RoundHouse folder

The first step is to create the folder that will contain all the SQL scripts for RoundHouse, and make sure it’s included in the source control for the project. You will also want to create the individual sub-folders that RoundHouse uses. Here are the default folders for RoundHouse:

alterDatabase\
runBeforeUp\
up\
runFirstAfterUp\
functions\
views\
sprocs\
indexes\
runAfterOtherAnytimeScripts\
permissions\

All these folders will be empty to begin with. We’ll populate a few scripts in the permissions folder, but other than that there’s no need to create sql scripts at this time. You’ll only need to start creating scripts when you want to change the database in the future.

Make a backup of the Database

Now you will want to take a backup of the database, but don’t include the data in the backup. It should just contain the schema, sprocs, views, etc. Create another folder called restore and copy the backup file to it.

RoundHouse will skip this backup script during regular deployments. But it will be available to use when we want to stand up the database on a new server.

Create the Permissions scripts

The last step is to create the necessary permission scripts for the database. If the database is located in multiple environments with permissions specific to each environment, then you’ll want to create a separate permission script per environment.

Fortunately RoundHouse makes it easy to create environment specific scripts. It provides a simple naming convention to denote which environment the script is supposed to be applied to.

The naming convention for environment specific scripts is: {EnvironmentName}.scriptName.ENV.sql

So LOCAL.sproc_permissions.ENV.sql will be ran in the LOCAL environment, and TEST.sproc_permissions.ENV.sql will be ran in the TEST environment.

Run RoundHouse

And now you’re ready to perform your first automated database deployment with RoundHouse. So run the RoundHouse console app in the folder you just made and point it to the database you’re using. You can find the exact command line arguments you need in RoundHouse’s documentation.

This first deployment you perform won’t do much because the only scripts it will run are the permissions scripts. But if you look at the database tables, you will notice RoundHouse added 3 new tables that it uses to keep track of the scripts it applies to the database.

Going Forward

Now when you want to make a change to the database, don’t update the database directly, but instead create a script in the ‘up’ folder. And then run RoundHouse and see how it finds the script you added and applies to the database for you.

And that’s really all there is to get up and running on RoundHouse. I was surprised by how little work was actually required to RoundHousify a database, which is another reason why I like RoundHouse!

Angular Directive’s Link function not being called

Last week as I was creating a custom Angular directive, I noticed that the link function was no longer being called after I added a compile function to the directive’s definition.

I was surprised that I wasn’t able to find an answer to this issue after doing a quick Google search, but I finally found an answer.

When the compile function is defined on the directive, then it should return the link function. This also means there’s no need to define the link property on the directive’s definition.

So instead of looking like this:

angular.module('myModule', []).
  directive('myDriective', function() {
    return {
      compile: function(elem, attrs) {
        // compile code
      },
      link: function(scope, elem, attrs) {
        // link code
      }
    };
  });

It should look like this:

angular.module('myModule', []).
  directive('myDriective', function() {
    var linkFunction = function(scope, elem, attrs) {
      // link code
    };
    return {
      compile: function(elem, attrs) {
        // compile code
        return linkFunction;
      }
    };
  });

Using Dreamhost for Heroku’s SSL Cert

The SSL certificate for my Heroku app is expiring in a few days, and I wanted to see if I could use Dreamhost for Heroku’s SSL certificate.  I had previously used GoDaddy, but their certificates cost $49 whereas Dreamhost only cost $15 for a year.

I tried finding documentation online as to whether a Dreamhost certificate will work with Heroku, but I wasn’t able to find much, so I gave it a try myself.

And it turns out that a SSL certificate from Dreamhost does work with Heroku.

Here are the basic instructions for updating a Heroku’s SSL cert with one from Dreamhost.

  1. Login to Dreamhost’s web panel and purchase an SSL certificate for your domain
  2. Once the SSL certificate has been granted, you can access it from the Web Panel
    1. Menu -> Domains -> Secure Hosting
    2. Find the certificate under ‘Secure Certificates’ section
    3. Click on the ‘View’ link to the right of the certificate
    4. Click on the ‘Keys’ tab to see the certificate and private key
  3. There are 3 parts to the certificate: The certificate itself, the private key, and the intermediate certificate
  4. Open a text editor and copy the contents of the Certificate to the file
  5. Then copy the contents of the Intermediate Certificate and paste it to the end of the file
    1. Make sure there is a blank line between the Certificate and Intermediate Certificate
  6. Save the file as domain.pem
  7. Copy the contents of the Prive Key and save it to a separate file named private.key
  8. Now you’re ready to upload the certicate to Heroku
  9. First make sure you have the heroku-ssl-doctor plugin installed (note that this plugin will eventually be included in the core heroku toolbelt and will no longer need to be installed separately)
    1. run heroku plugins to see the list of plugins installed
    2. If it’s not installed run the following command to install it: heroku plugins:install https://github.com/heroku/heroku-ssl-doctor.git
    3. this plugin will sort out everything with your certificate and ensure you have a complete trust chain.
  10. If you don’t have a certificate already installed on heroku, run heroku certs:add domain.pem private.key
  11. If you already have a certificate installed, run heroku certs:update domain.pem private.key

It might take a couple hours for browsers to recognize the new certificate, but you should be good to go.

Getting MS Access to work with NHibernate

I am continuing to play with NHibernate and wanted to use MS Access as the database back end. I thought it would be an easy migration that required only a couple NHibernate configuration settings being changed below.

<pre><property name="dialect">
  NHibernate.JetDriver.JetDialect, NHibernate.JetDriver
</property>
<property name="connection.driver_class">
  NHibernate.JetDriver.JetDriver, NHibernate.JetDriver
</property>
<property name="connection.connection_string">
  Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db1.mdb
</property>

But when I started up NHibernate, I received the following error:

System.IO.FileNotFoundException: Could not load file or assembly ‘NHibernate.JetDriver’ or one of its dependencies. The system cannot find the file specified.

File name: ‘NHibernate.JetDriver’

It turns out I needed to add the NHibernate.JetDriver DLL to the project. This DLL is not part of the main NHibernate project. It is located in the NHibernate Contrib Project on Source Forge.

Building the NHibernate.JetDriver

  1. Checkout the source code from Source Forge
  2. Build the NHibernate.JetDriver project
    1. Directory Location from trunk: /trunk/src/NHibernate.JetDriver
    2. The easiest way to build it is using the NAnt script included in the project (default.build)
      1. The NAnt script creates a “build” folder and places the driver in there
    3. You can also open the project and build it from there
      1. The driver will be located in: NHibernate.JetDriver\bin\Debug

Once you create the NHibernate.JetDriver all you need to do it copy it to your project directory and reference it from your project and then you should be good to use MS Access with NHibernate.