Navigation
CATEGORY: Uncategorized

Why I recommend EmberJS over AngularJS

tldr: scroll down and read the headlines and bold words to get a quick overview.

For the past couple years I have absolutely loved developing web applications with AngularJS. Angular has made it so easy to provide the advance user experience that people are coming to expect. And as a developer I have enjoyed how easy Angular has made two way databinding and unit testing the JavaScript code with its built in dependency injection.

Everything was awesome!

But then the Angular team announced their plans for Angular 2.0 and everything was no longer awesome.

When the Angular team announced version 2.0 would be a complete rewrite, I felt like a good friend had just abandoned me.

Although the Angular team said there would eventually be an upgrade path, I didn’t believe them. A framework rewrite almost always means rewriting apps that use the framework.

(3/10/2015 Update: Last week during NgConf the Angular team proved me wrong by sharing it will be possible to incrementally upgrade an app to 2.0 without rewriting everything at once. I must say, I am impressed. It still doesn’t change my recommendation for Ember over Angular, but I am happy to hear about it.)

I was upset. So I started looking at other JavaScript frameworks. I wanted to make sure there wasn’t another framework out there that was competitive with Angular.

And that’s when I found the EmberJS framework.

Ember has been out for a couple years now, and I have been hearing a little bit about it here and there from other JavaScript developers online, but I had never spent any time looking into it. I saw that CodeSchool had a course on it, so I signed up for the course and starting going through it.

Learning Ember

As I was learning Ember, I realized right away that Ember was not Angular, and it had its own way to structure a JavaScript application. Unlike Angular, Ember is a very opinionated framework which forces you to structure your app the way it wants you to. And if you don’t follow its guidelines, then you’ll quickly find yourself fighting against the framework.

Honestly, I was kind of annoyed with how opinionated Ember was, but then something happened that completely changed my mind on the matter. Let me share.

About six hours into learning Ember, I decided to take a break from the course and take a look at the source code for a production app that was using Ember. I knew the Discourse forum software was open source and built with Ember. So I found its Github page and started browsing its Ember code.

I opened a template file and looked through it. I saw that it was displaying a value from a property, so I opened the controller file associated with the template. I saw the property was actually a computed property based upon the controller’s model. Next, I browsed to the controller’s associated route and saw how the controller’s model was retrieved. I then went back to the template file and saw that a view helper was being used, so I opened the view helper file to see what it was doing.

And then I distinctly remember pausing and thinking something didn’t feel right. Something was off, but I couldn’t put my finger on it. And then it hit me: I was actually understanding the code base for a project I had never looked at before.

For a project the size of Discourse, it typically takes a few hours to a few days to just begin to understand its code base. But Ember’s strong opinions and conventions allowed me to open a project I had never seen before and understand what was going on in only a few minutes.

And that’s when my opinion about Ember changed. Up until that point I had been hesitant about Ember and didn’t think it was better than Angular. But that experience browsing the source code of a production Ember app helped me begin to understand Ember’s benefits over Angular.

I then I began learning all I could about Ember. And the more I learned about Ember and its community, the more I appreciated Ember. And now I fully recommend Ember over Angular. Let me share my reasons why.

Why I Recommend Ember over Angular

My reasons for recommending Ember over Angular are not the typical reasons given by developers when they recommend a framework. But once you read my explanation for each reason, I hope you’ll also see the benefits Ember has.

But before I share my reasons for Ember, I want to share some reasons that did not affect my decision.

Reasons that did not affect my decision

It doesn’t have new functionality

Anything you can do in Angular, you can do in Ember. And anything you can do in Ember, you can do in Angular. Both frameworks can provide the same functionality to the end user.

To be sure, how you implement a feature (like a modal, or sorting a table) is different in Ember versus Angular, but the end result is the same. The user would notice no difference if the website was built with Ember or Angular. So difference in functionality is not a reason for my Ember recommendation.

It’s not the next shiny new toy

It could be argued that I have the Shiny New Toy Syndrome because every couple of years I’m advocating for a new JavaScript framework. It started with Backbone, then a couple of years later I started advocating for Angular, and now it’s Ember.

I would argue I don’t have the shiny new toy syndrome, though, because each framework I have advocated for had benefits over the previous framework of choice.

The reason I have changed my recommended JavaScript frameworks so much is because the JavaScript framework ecosystem itself is still in its infancy and has not matured yet. It seems every week there is a new JavaScript framework created.

It’s not cool to change frameworks just because there is a new framework out. There must be a business reason to change. And as you’ll read below, I would argue there are some very good business reasons to move to Ember.

Reasons that did affect my decision

The Core Team

When deciding between frameworks, the members of the core team usually don’t affect my decision making process. But this time it did affect my decision to choose Ember over Angular. And actually, it was one of the main deciding factors for me.

Here’s why: every member on Ember’s core team is actively working on one or more production apps that use Ember.

Let me explain why this is so important to me.

When everyone on the core team has their own production apps using the framework, then the core team is forced to experience all the joys and pains of using the framework, just like every other developer does. And this means the core team will naturally look out for the good of all developers using the framework.

On the flip side, when the core team members don’t use the framework on production apps, then “the sky is the limit!” It’s easy to forget about the developers using the framework as they dream up new features. Framework designers don’t feel pain in brainstorming meetings.

Angular 2.0 is a perfect case in point for this situation. One reason they are going forward with a complete rewrite of the framework is because the core team members will not experience the pain of rewriting an app to migrate from version 1.x to 2.0. But you can be sure the Ember team won’t do the same thing because they also would have to rewrite their apps.

Another example of what happens when the core team dogfoods their own framework is Ember CLI. The main reason the core team is developing Ember CLI is because they not only see its benefit but also experience its benefit. I’ll go into more detail on Ember CLI below.

Like I mentioned, I haven’t heard many others look at the members of the framework’s core team, and use them as a reason for choosing one framework over another. But to me, it’s one of the most significant reasons for my decision.

Guidance is set by those with the most experience

So here’s a question: Who do you want to set the guidance and best practices for using a framework? Developers with some experience using the framework or developers that actually created the framework?

That’s the difference between Angular and Ember.

Angular doesn’t provide much guidance on how to use the framework, so it becomes the wild west when a company first adopts Angular. Every team uses the framework however they see fit. But eventually it does come to a head when the company realizes a developer can no longer easily switch teams because the framework is used so differently between teams. Then a few developers from different teams get together and come up with the company’s official guidance and best practices for using the framework.

But then that guidance only applies to apps created going forward. The apps that are already using the framework are grandfathered in because it would take too much time to refactor them. So it’s still difficult for developers to switch teams because there’s still legacy apps. And the developers that created the guidance only went off their own experience and features they had to create. They didn’t experience all the edge cases, so the guidance is in constant flux as new scenarios are coming up.

Here’s a case in point: there are four development teams currently using Angular at my work place, and every team has structured their Angular app differently. There is no consistency even though we’re all using the same framework. And we have literally spent multiple days worth of time discussing and debating how our apps should be structured. And they are still not structured the same way.

Ember, on the other hand, has its guidance and best practices set by its core team members. And these guidances and best practices are baked directly into the framework, so it’s easy to follow.

Because Ember specifically defines how an application should be structured, the developers do not waste hours upon hours debating how an app should be structured. Instead they can spend that time actually developing the app and providing value to the business.

It also means new team members that already know Ember can become productive in any Ember app within minutes because they know how the app is structured and where to go to add a new feature or fix a bug. Like I shared above, after only spending a few hours learning Ember, I was able to browse and understand the structure of a large Ember application. That can’t be said for most developers learning Angular.

Use 2.0 features in the 1.x version series

Many new features are being added for Ember version 2.0, yet when version 2.0 is finally released, it won’t contain any new features. I know, it doesn’t make sense. It didn’t make sense to me at first either. But after I understood Ember’s versioning process it finally did make sense to me. And it turns out Ember’s versioning process is pretty cool.

The reason no new features will be introduced when Ember 2.0 is released is because all the 2.0 features will have already been introduced in the 1.x version releases.

The Ember team has a lot of new features they want to add to Ember 2.0, but they’re not waiting for 2.0 to implement them. They’re introducing the 2.0 features in version 1.x as they complete them. For example, that means Ember apps can take advantage of using the react style virtual DOM for increased speed, whereas Angular developers need to wait until Angular 2.0 comes out.

Another cool feature being added to Ember is Fast Boot. This allows an Ember app to serve HTML that’s already populated with data when a user first comes to the site. This means the user doesn’t have to wait for all the JavaScript files to be parsed and the initial AJAX calls to be made before they can see the data on the page. It’s all there in the initial HTML that is served up. Then after the JavaScript files are parsed, the page turns into a normal Single Page App (SPA).

So if nothing new is being introduced when Ember 2.0 is releaseed, what actually changes when it’s released? Basically the deprecation warnings in 1.x go away and if you had any deprecation warnings, then that code no longer works.

Ember CLI

Ember CLI is a game changer for Ember. And it will make all other JavaScript frameworks absolutely jealous. It not only streamlines developing Ember apps, but it also makes it super easy to share common code among different Ember apps. And all this results in making Ember developers more productive.

Ember CLI takes care of all the grunt work that’s involved in adding new third party libraries and code to the app.

For example, let’s say you want to add a date picker to your Ember app. With Ember CLI, all you have to do is execute the following command and you can immediately use the datepicker addon:

  1. ember install:addon ember-cli-datepicker

Now compare that with the typical set of steps required to install an addon without using Ember CLI:

  1. Download the addon (typically with bower or npm)
  2. Update the build config to include the addon’s javascript
  3. Update the build config to include the addon’s css
  4. Update the app’s dependencies to include the addon

As you can see, Ember CLI combines these four steps into a single command. And sure, these four steps only take a minute or two to perform manually, but that time quickly adds up over the lifetime of developing an application.

Another major feature in Ember CLI is blueprints. These are snippet generators that automatically add the scaffolding code required when creating new features in your Ember app.

Here’s an example of using Ember CLI to create a new route named foo:

ember generate route foo

installing
  create app/routes/foo.js
  create app/templates/foo.hbs
installing
  create tests/unit/routes/foo-test.js

So with one command, not only are all the necessary files created, but each file is stubbed out with the necessary scaffolding code and ready for you to actually write your application specific logic.

For example, here is the contents for the test/unit/routes/foo-test.js file that was generated:

import {
  moduleFor,
  test
} from 'ember-qunit';

moduleFor('route:foo', 'FooRoute', {
  // Specify the other units that are required for this test.
  // needs: ['controller:foo']
});

test('it exists', function() {
  var route = this.subject();
  ok(route);
});

And now you can focus on writing your tests instead of spending a minute or two writing the plumbing code required before you can start testing.

No other JavaScript framework I know of has a command line utility like Ember CLI. So while developers on other JavaScript frameworks spend time writing plumbing code and updating their builds when adding third party libraries, Ember developers have that much more time to actually write their apps.

Conclusion

Don’t get me wrong, I believe Angular 2.0 will be great, and I have enjoyed writing web applications in Angular 1.x. The complete rewrite for Angular 2.0 has really turned me off from the framework, though, and it made me realize there’s another framework out there that looks out for the developer more than Angular.

So I encourage you to give Ember a try. I think you’ll find it has some great benefits just like I did.

Debounce Search Filter in EmberJS

A common piece of functionality that I typically include in my web applications is the ability for users to quickly filter the data displayed on the page. A simple text box is often used to provide the filtering.

It’s pretty easy to bind a text box to a property on the controller and filter the results by the value in the text box. But this also means that the filter is performed after every keystroke the user enters. For small datasets this is fine, but for large datasets it can cause the UI to start locking up. So it’s better to wait until the user has finished entering the filter text before actually performing the filter.

I’m going to share three ways to perform filtering in Ember, starting with applying the filter immediately after each keystroke, and then go on to show how to apply the filter when the user clicks a button, and finally how to apply the filter after the user has stopped entering text in the filter text box.

Filter Immediately

Applying the filter immediately is straightforward in Ember. You just need a text box that’s bound to a property on the controller. And the controller will also have a computed property that returns the filtered results. This computed property will be re-calculated anytime the filter text changes.

Here’s a basic example of how that looks:

App.IndexController = Ember.Controller.extend({
  filterText: '',
  filteredResults: function() {
    var filter = this.get('filterText');
    return this.get('model').filter(function(item) {
      return item.toLowerCase().indexOf(filter) !== -1;
    });
  }.property('filterText')
});
<script type='text/x-handlebars' data-template-name='index'>
  {{input value=filterText type='text' placeholder='filter'}}
  <ul>
    {{#each item in filteredResults}}
      <li>{{item}}</li>
    {{/each}}
  </ul>
</script>

JS Bin Example

Filter on Demand

The easiest way to mitigate the filter being applied after every keystroke is to wait until the user clicks a button to apply the filter. In this scenario the filterText property on the controller will still be bound to the text box and will be updated with every keystroke. That means we can no longer apply the filter when the filterText property changes.

We’ll need to create an additional property called filter that keeps track of the current filter value. And the filteredResults computed property will now be dependent upon filter instead of filterText.

And the last change we’ll need to make is to add the applyFilter action to the controller. When this is called after the user clicks the button, it will copy the value from filterText to filter and cause the filteredResults to be re-computed.

App.IndexController = Ember.Controller.extend({
  filter: '',
  filterText: '',
  filteredResults: function() {
    var filter = this.get('filter');
    return this.get('model').filter(function(item) {
      return item.toLowerCase().indexOf(filter) !== -1;
    });
  }.property('filter'),
  actions: {
    applyFilter: function() {
      this.set('filter', this.get('filterText'));
    }
  }
});
<script type="text/x-handlebars" data-template-name="index">
  {{input value=filterText type='text' placeholder='filter'}}
  <button {{action 'applyFilter'}}>Apply Filter</button>
  <ul>
    {{#each item in filteredResults}}
      <li>{{item}}</li>
    {{/each}}
  </ul>
</script>

JS Bin Example

This does the job, but it doesn’t provide the best experience for the user because they have to click the filter button each time. What would be better is to wait until the user is done typing in the filter text box and then automatically apply the filter.

Filter on Pause

To wait to perform the filter until the user has finished entering the filter value, we’ll use the Ember.run.debounce function.

In case you don’t have much experience with a debounce function, let me explain how it works.

When you call debounce, you tell it what function you want called and how long it should wait to call the function. For example, you can tell debounce to call a function named updateQuotes in 5 seconds. And debounce will set a timer for 5 seconds and call updateQuotes when the timer has elapsed.

However, if debounce is called again before the timer completes, then the timer is reset and starts counting down again. And the function will not be called as long as debounce is called again before the timer completes.

We’ll use debounce’s functionality to automatically apply the filter after the user finishes entering the value they want to filter by.

Here is how that looks:

App.IndexController = Ember.Controller.extend({
  filter: '',
  filterText: '',

  onFilterTextChange: function() {
    // wait 1 second before applying the filter
    Ember.run.debounce(this, this.applyFilter, 1000);
  }.observes('filterText'),

  applyFilter: function() {
    this.set('filter', this.get('filterText'));
  },

  filteredResults: function() {
    var filter = this.get('filter');
    return this.get('model').filter(function(item) {
      return item.toLowerCase().indexOf(filter) !== -1;
    });
  }.property('filter')

JS Bin Example

Using Ember Data with Asp.Net Web API

Last week I started playing around using EmberJS with an Asp.Net Web API backend. And one of the first issues I ran into was getting Ember and Asp Web API to actually communicate with other.

But the first time I tried to retrieve data from the server, Ember Data threw the following exception:

Error while processing route: posts Assertion Failed: You must include an `id` for App.Product in an object passed to `push`

What was going on? After some quick reading through the Ember Data documentation, I realized Ember Data expects the JSON data returned from the server to be in a different format than Asp.Net Web API was returning.

Ember Data expects the JSON data to and from the server to look like this:

{
  posts: [{
    id: 1,
    title: 'First Post'
    publishDate: '2014-11-07'
  }, {
    id: 2,
    title: 'Second Post'
    publishDate: '2014-11-14'
  }]
}

But Asp.Net Web API expects the JSON data to look like this:

[
  {
    Id: 1,
    Title: 'First Post',
    PublishDate: '2014-11-07'
  }, {
    Id: 2,
    Title: 'Second Post',
    PublishDate: '2014-11-14'
  }
]

Notice there are two main differences here between the data formats. First, Ember Data expects a root node named posts to contain the array of posts. But the Web API just returns the array of posts. And second, Ember Data expects the property names to be camelCased. But the Web API has PascalCased property names.

Fortunately Ember Data makes it easy to massage the data that’s coming from and being sent to the server. This means you don’t have to change the default way that Asp.Net Web API serves data.

Massage the data with Serializers

Ember Data uses objects called Serializers to massage and map the data format from the server to the format Ember expects (and vice versa).

Ember includes a few default Serializers for you in its framework that you can choose to use. There’s the JSONSerializer and also the RESTSerializer that extends the JSONSerializer. The RESTSerializer provides most of the mapping we already need. So we will extend it and will only need override a couple functions to perform our specific mapping.

Let’s first map the data coming from the server into the format Ember expects. We will do this by overriding the extract method.

App.ApplicationSerializer = DS.RESTSerializer.extend({
  extract: function(store, primaryType, payload, id, requestType) {
    ...
  }
});

You can see there are quite a few arguments for the extract method, but we are only concerned about two of them: the payload and the primaryType. The payload contains the raw response from the server, and the primaryType will tell us the name of the root node to include in the result.

Let’s first convert the PascalCased property names from the server to camelCased names that Ember expects.

extract: function(store, primaryType, payload, id, requestType) {
  var i, record, propertyName, value, newPropertyName;
  for (i = 0; i < payload.length; i++) {
    record = payload[i];
    for (propertyName in record) {
      value = record[propertyName];
      newPropertyName = propertyName.camelize();
      record[newPropertyName] = value;
      delete record[propertyName];
    }
  }
}

Notice we’re taking advantage of the camelize() function that Ember adds to all string objects. This function takes care of renaming the property to camelCase. So PublishedDate becomes publishedDate with the camelize() function.

Now we need to add the root element to the payload that Ember is expecting.

{
  //root node
  posts: [{...}]
}

And that means we need to retrieve the name for the root element. We can get that information from the primaryType argument. It has a property on it called typeKey that holds the value for the expected root element name.

extract: function(store, primaryType, payload, id, requestType) {
  //... previous code ...
  payloadWithRoot = {}
  payloadWithRoot[primaryType.typeKey] = payload

  this._super(store, primaryType, payloadWithRoot, id, requestType);
}

And the last thing we do is call the _super function to allow the default RESTSerializer to continue on with the normal extraction.

Before we move on, let’s refactor the code so it works with both arrays and single objects that are returned from the server.

App.ApplicationSerializer = DS.RESTSerializer.extend({
  extract: function(store, primaryType, payload, id, requestType) {
    var i, record, payloadWithRoot;
    // if the payload has a length property, then we know it's an array
    if (payload.length) {
      for (i = 0; i < payload.length; i++) {
        record = payload[i];
        this.mapRecord(record);
      }
    } else {
      // payload is a single object instead of an array
      this.mapRecord(payload);
    }
    payloadWithRoot = {}
    payloadWithRoot[primaryType.typeKey] = payload
    this._super(store, primaryType, payloadWithRoot, id, requestType);
  },
  mapRecord: function(record) {
    var propertyName, value, newPropertyName;
    for (propertyName in record.toJSON()) {
      value = item[propertyName];
      newPropertyName = propertyName.camelize();
      item[newPropertyName] = value;
      delete item[propertyName];
    }
  }
});

That’s all it takes to massage the data coming from the server. Now we need to massage the data that is sent down to the server from Ember. And fortunately this is much easier than the other way around.

To do this, we will override the serializeIntoHash function.

serializeIntoHash takes four arguments, but we’re only concerned about two of them. The record argument is the model that is to be saved to the database, and the hash argument is the actual JSON object that will be sent to the server.

So all we need to do is loop through the properties and values in the record object and copy them over to the hash object. And during the copy, we’ll transform the property name to PascalCase.

App.ApplicationSerializer = DS.RESTSerializer.extend({
  extract: function(store, primaryType, payload, id, requestType) {
    ...
  },
  mapRecord: function(record) {
    ...
  },
  serializeIntoHash: function(hash, type, record, options) {
    var jsonRecord, propertyName, value;
    jsonRecord = record.toJSON();
    for (propertyName in jsonRecord) {
      value = jsonRecord[propertyName];
      hash[propertyName.capitalize()] = value;
    }
  }
});

And as you can see, the Ember framework provides the capitalize() function on string objects, and it will take care of transforming the property names to PascalCase.

Conclusion

Ember Data has a bit of a learning curve to understand it. But I really appreciate the amount of thought that went into its design so that it can provide the needed flexibility to work with multiple server backends, including Asp.Net Web API.

Ember Data has a bit of a learning curve to understand it at first. But I really appreciate the amount of thought that went into its design. This is evident in how easy it is to work with multiple API backends, including Asp.Net Web API.

Complete Solution

Here’s the complete solution as a reference.

App.ApplicationSerializer = DS.RESTSerializer.extend({
  extract: function(store, primaryType, payload, id, requestType) {
    var i, record, payloadWithRoot;
    // if the payload has a length property, then we know it's an array
    if (payload.length) {
      for (i = 0; i < payload.length; i++) {
        record = payload[i];
        this.mapRecord(record);
      }
    } else {
      // payload is a single object instead of an array
      this.mapRecord(payload);
    }
    payloadWithRoot = {}
    payloadWithRoot[primaryType.typeKey] = payload
    this._super(store, primaryType, payloadWithRoot, id, requestType);
  },
  mapRecord: function(record) {
    var propertyName, value, newPropertyName;
    for (propertyName in record.toJSON()) {
      value = item[propertyName];
      newPropertyName = propertyName.camelize();
      item[newPropertyName] = value;
      delete item[propertyName];
    }
  },
  serializeIntoHash: function(hash, type, record, options) {
    var jsonRecord, propertyName, value;
    jsonRecord = record.toJSON();
    for (propertyName in jsonRecord) {
      value = jsonRecord[propertyName];
      hash[propertyName.capitalize()] = value;
    }
  }
});

Chaining Promises to Cleanup Your Angular Codebase

I’ve been using promises in JavaScript for a while now and thought I knew almost everything about them. But yesterday a co-worker showed me how it’s possible to manipulate the resolved value from one promise to another when they are chained together. Let me show you what I mean.

Below is a chained promise that logs the name to the console. It’s pretty straight forward.

getName().then(function(name) {
  console.log(name);
}).then(function(name) {
  console.log(name);
});

> 'Paul'
> 'Paul'

Now let’s have the first then function append a last name and return it. And now notice the output of the second log statement:

getName().then(function(name) {
  console.log(name);
  return name + ' Yoder';
}).then(function(name) {
  console.log(name);
});

> 'Paul'
> 'Paul Yoder'

In the first example, both then functions received the same resolved value from the original promise. But in the second example, the first then function returned a different value, and the second then function received that different value instead of the original value from the promise.

Applying Chained Promises to Angular

I was able to clean up a lot of my Angular code after finding out about this feature for chained promises. Here’s one example of how I was able to clean up the code.

Let’s say you have a REST API that returns information about a specific company. And the return value looks something like this:

{
  companyName: 'ACME',
  phone: '402-555-5555',
  employeeCount: 100
}

And you have an Angular service that consumes the REST endpoint and returns the employee count for the company. And it looks something like this:

angular.module('app').factory('employeeCountService', function($http, $q) {
  return {
    getByCompanyId: function(companyId) {
      var deferred = $q.deferred()
      $http.get('/companies/' + companyId).then(function(companyInfo) {
        deferred.resolve(companyInfo.employeeCount);
      });
      return deferred.promise;
    }
  };
});

// Here's a controller that uses the companyEmployeeCount service
angular.module('app').controller('HomeCtrl', function($scope, employeeCountService, companyId) {
  employeeCountService.getByCompanyId(companyId).then(function(employeeCount) {
    $scope.employeeCount = employeeCount;
  });
});

Notice that $q.deferred was used because we had to manipulate the returned value from the REST API and resolve the promise to only include the employee count.

By taking advantage of what we just learned about chained promises though, we can clean up the amount of code needed in the employeeCountService service to the following:

angular.module('app').factory('employeeCountService', function($http) {
  return {
    getByCompanyId: function(companyId) {
      $http.get('/companies/' + companyId).then(function(companyInfo) {
        return companyInfo.employeeCount;
      });
    }
  };
});

The controller code that uses employeeCountService did not change, and the getByCompanyId function no longer has to create its own deferred object. So there’s less code and it’s easier to understand, and I consider that a big win!

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.