Date

So, as I mentioned before I've been doing more work in Angular lateley. Enough that I am pretty egar for the 2.0 release. There are just too many ways to shoot yourself in the foot the way Angular is now.

One of the really cool features has always been the directives, which if you are just getting started, may seem crazy. That is until you grasp the basic concepts.

Directives allow you to better modularize pieces of your app or web page. From our early days learning software development we are told modular is good.

It helps us keep things organized and reusable (at least within the same application). Angular directives allow not only our logic to be modular, but the HTML markup too!

Consider this markup for a fictional contact form:

Let's say you wanted to use this in two places:

  1. The contact page/tab.
  2. A modal that pops up after some specified length of time.

Now in traditional client side development, we might be tempted to simply cut and paste the form into the places we intend to use it.

Indeed when you are on a deadline this often saves some headache. That is of course until you realize you forget something and have to make some edits.

Each time you copy the same template somewhere else in your app you make future maintenence a little harder.

Let's not copy and paste, let's use a directive instead:

For something as simple as displaying a form, that's all you need. What this does is tell angular to create a directive called contactGeneric.

The restrict:'E' part means this directive must be used like an html element. So for this particular directive you would use it as <contact-generic></contact-generic in your markup.

Note: Angular requires directives to be declared in camel case but they are normalized automatically. Late at night this can get to you when creating templates and your custom directives appear to be ignored. Usually because you were writing <contactGeneric></contactGeneric> or even:

angular.directive('contact-generic', function () {

          return {
            restrict: 'E',
            templateUrl: 'contactGeneric.html'
          }
 });

That got me a few times, my advice? Don't code with Angular when you are tired. In this particular directive, the templateUrl is the most important part. Whatever we provide here, Angular will attempt to load and render that when it's time to show our <contact-generic></contact-generic>.

That means anywhere in our app we place that tag, the html from this url will show. Nice huh? Now you don't have to maintain all those extra copies. Just one.

Supposedly the upcoming Web Components spec will allow us to do something similar in any browser without need for third party frameworks. To be honest though, I have not paid much attention to Web Components just yet. The concept is most welcome regardless of how it is achieved though.

Now this directive is pretty lame as it is. What about validation? Conditional fields? Populating the <select> with remote data? With Angular, the validation part is easy, and you can use ngShow or ngDisabled to prevent filling out certain fields based on some variable.

The remote data part is also simple, normally we would do the actual fetching of data from a controller so let's give this directive one.

Note: There is more than one way to assign controllers to directives. I've found that depending on the build tools you use, you tend to prefer one over the other.

You can:

  • Register a controller via app.controller or
  • Use an inline function.

I like inline functions:

So this directive will fetch data from the back end each time it is shown. Note the bindToController and controllerAs properties. These essentially allow me to get rid of references to $scope which is nice.

Rather than attaching properties to $scope, you attach them to the controller and they will be accessible in the template via contactGeneric.propertyName.

That's it for now. If you use tools such as browserify to build your JavaScript you can actually replace the templateUrl property with template and load the contents of the whole file using the partialify transform.

I'll try to get to that another time, I do this but my work-flow is far from perfect at the moment. :)


Comments

comments powered by Disqus