The Code Dump

A place a coder rants at...

Controller-Directive Communication Part 3: Controller to Directive

| Comments

This is the last part of my controller and directive communication series. In the first part we looked at setting up simple bindings. The second part showed the use of bound functions to let the directive send messages up to the controller.

This part focuses on the remaining combination: having the controller send messages down to the directive.

Controller to Directive Communication

Continuing with the chat app example from the previous parts, let’s now assume that our controller sometimes wants to tell the chat list to scroll to the bottom (e.g. because the user marked the chat as read from another device).

This means that now our controller needs to somehow tell the directive to do something. We want the directive to expose something to us. Directives can receive functions via bindings, but there’s no straightforward way for them to create new bound functions and expose them up the chain.

The Suboptimal Options

There are a few possible techniques that are somewhat popular/recommended at some places. I’m listing them here mainly to say why I dislike them – scroll down to my preferred solution if you’re in a hurry.

Events? I’d Rather Not

A lot of developers would just shrug and use events (Using $scope.$broadcast, $scope.$on and $scope.$emit).

While this will work, I find events to be catalysts for code quality deterioration.

Using events means you have to dig through a component’s code to find which events it is firing or watching for. There’s no easy-to-find API to understand the dependencies between components.

Services? Not really

Services are the go-to for communication between entities in many Angular scenarios, and they rightly are. But this scenario feels different.

This isn’t a a concern that’s relevant across the whole app. It’s internal communication between two instances on screen, that would feel wrong for me to put in a service.

I prefer to use services for things that are global – cross cutting concerns that are synced across the app, and not a component and its inner component trying to nudge a pixel.

Scope Mangling

I don’t really have a name for this one, but I’ve seen it in the wild. It’s an abuse of binding to slap on things on objects willy-nilly.

Basically, our controller creates some object, e.g. directiveApi = {}. That object is then passed with binding to our directive. During its initialization the directive would add functions to this object (scope.directiveApi.onRealAll = function() {}).

That way the controller now has a reference to a function that was created by the directive, and can call it at will.

This feels like one big hack to me. My aesthetics always prefer the explicit solution, the one that’s least likely to shoot me in the foot.

It also introduces implicit coupling and just feels scary when you read the controller’s code – all of a sudden it makes a call to a function you’ve never seen before.

Also, it introduces a timing issue – you have to make sure not to attempt to call these functions before the directive finished its initialization. Scary.

My preferred solution – The Observer Pattern

In this case I’d rather implement my own observer pattern, even though it would require some boilerplate code, in order to avoid using events or external services.

Here’s how it goes. Our controller now manages observers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
angular.module('chat').controller('ChatCtrl', function(ChatService) {
  var chat = this;
  var handlers = [];
  chat.markAsRead = markAsRead;
  chat.onAllRead = onAllRead;
  activate();

  function activate() { /* Setup */ }

  function markAsRead() {
    ChatService.markAsRead();
    angular.forEach(handlers, function(handler) {
      handler();
    });
  }

  function onAllRead(handler) {
    handlers.push(handler);
  }
});

And the directive looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
angular.module('chat').directive('chatMessageList', function() {
  return {
    scope: {
      list: '=chatMessageList',
      onAllRead: '&' // The registration hook
    },
    template: 'something', // See full plunker
    link: function(scope, element) {
      var $list = $(element).find('.js-chat-list');
      scope.onAllRead({
        handler: function() { scrollToBottom($list); }
      });
    }
  };
});

Full Plunker Example

We’re using the isolated scope in order to pass the directive a function, onAllRead, but this time that function is used by the directive to register for change notifications on the controller.

ChatCtrl saves the directive’s handler and will make sure to call it whenever it needs to notify someone about this.

This requires more typing, but I prefer it since our code is now very clear. It’s really easy to understand the flow even if you are unfamiliar with the codebase and stumbled upon any one of our source files by its own.

It is also more robust. If we ever move things around and forget to update all the sources it would break at a useful point – when the directive would try to register to a function that is no longer there. In other scenarios, like scope mangling, it would break when the controller would try to send the notification to no one.

As a rule of thumb, this is the way I’d go with most of the time unless I have a pretty good reason to use something else.

Note: When passing functions by yourself to other places in Angular, like we do in this case, you should make sure those functions are no longer kept anywhere once the scope they’re bound to is destroyed. Failing to do that would mean memory leaks and undefined behavior. Check out the full plunker example to see how exactly this is done.

That’s it. I’m more than interested in feedback about this, feel free to contact me. The important takeaway is that Angular is not trivial for communication between parts, but that doesn’t mean you shouldn’t be breaking your system to small, maintainable chunks.

Controller-Directive Communication: Part 2

| Comments

In the previous part we saw the simple case of a component, represented by a directive, that we use in our controllers in a simple set and forget setup: the component just needs some input and can do its job using that alone.

In those cases, using the simple magic of data-binding is really all you need. But once you go around the block a couple of times you’ll eventually come upon the need to write a smarter component.

This part will focus on a directive talking with its parent controller. That means we have a directive that would like to tell its parent that something has happened. Note that in cases of directive-to-parent-directive communication the best practice might be something else.

Directive to Controller Communication

Let’s say that we’re going to change the behavior of our chat app a bit. We don’t want the view to scroll to the newest message automatically now – we got plenty of users complaining about losing track of their place in conversations that way.

Instead, there’s no auto scrolling and we’ll want the chat list directive to let the controller know whenever the user scrolled to the bottom of the list, so the controller would know to mark that chat as read (e.g. in order to send a read receipt to the other party).

First, we add this function to our ChatCtrl (you can see the previous post’s code here):

1
2
3
chat.readMessages = function(lastMessageRead) {
  ChatService.markAsRead(lastMessageRead);
};

We pass it to the directive by adding read-messages="chat.readMessages(lastMessageRead)" in our template.

And we change our directive like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
angular.module('chat').directive('chatMessageList', function() {
  return {
    scope: {
      list: '=chatMessageList',
      readMessages: '&' // <-- This is new!
    },
    template: '<div class="chat-list js-chat-list">' +
                '<div ng-repeat="message in list">' +
                  '{{message.text}}' +
                '</div>' +
              '</div>',
    link: function(scope, element) {
      var $list = $(element).find('.js-chat-list');
      $list.on('scroll', function() {
        if (isScrolledToBottom($list)) {
          scope.$apply(function() {
            var lastMessage = scope.list[scope.list.length - 1];
            scope.readMessages({lastMessageRead: lastMessage); // <-- This too
          });
        }
      });
    }
  };
});

Full Plunker Example

As you can see, in this scenario we needed the directive to notify its parent controller of something. That was pretty easy to achieve – we used the isolated scope to pass along a callback function readMessages() that the directive can call whenever it needs to.

There are a few alternatives, like using events, but I’m pretty certain this is the way most Angular developers would go with for a scenario like this. It’s easy, clear and readable.

Passing Function Bindings

As you may have noticed, passing a function binding doesn’t look likely simply binding on some data. When we passed the chat list we specified it on the isolated scope as list: '=chatMessageList'. That equals sign means it’s a “simple” data binding – Angular keeps evaluating the expression that the parent controller passes the directive and if it notices a change it syncs it to the directive’s scope.

You can imagine that Angular just regularly checks the value of chat.messages in the parent controller and whenever the expression returns a different value (e.g. because we’ve put a different instance of a list there) it does something along the lines of directiveScope.list = controllerScope.chat.messages in order to bind them together.

Functions are different. With functions we don’t want Angular to regularly evaluate readMessages(lastMessageRead) – it doesn’t make sense. We want that function to run only on specific times, not on every digest cycle. Also, lastMessageRead doesn’t exist anywhere, it’s the name of an argument.

That’s why when we pass function bindings we have to use a different syntax when defining them in the scope, in this case readMessages: '&' – that ampersand is the way of saying this is a function binding.

Another detail is that we don’t call these functions like we define them. The original readMessages() function receives a single argument, so you might expect us to call it as scope.readMessages(message) – but that’s not how it’s done.

The syntax is a bit different, where we have to specify arguments to the functions inside a single object where the key names are the names of the arguments.

So scope.readMessages(message) turns into scope.readMessages({lastMessageRead: message}).

While you might find it odd the first couple of times, it’s really not that big of a deal and grows on you fast.

Function bindings are a very important building block in Angular in general and specifically in creating robust and reusable directives. Making it possible to create simple callbacks allows for a lot of flexibility.

The Way Forward

In the next part we’ll see how function bindings can be used to allow the controller to call the directive and notify it of changes. Make sure to get it by subscribing to my mailing list below.

Controller-Directive Communication: Scroll to Bottom

| Comments

A common question in Angular is how should two components talk to each other. The flexibility of Angular means you have a lot of choices to make, and there’s little guidance.

The way you’d have two sibling controllers communicate is different from how a controller will talk to its parent controller, how a directive will talk to its parent directive and how controllers and directives talk with one another.

In this part we’ll go over a common use-case, scroll to bottom, in order to show the straightforward way of communicating between controllers and directives: Set and forget.

The next 2 parts will be more in-depth about the communication itself in the scenarios of directive to controller communication and controller to directive communication.

Set and Forget + Scroll to Bottom Example

Say we have a simple chat client controller that is made of a list of messages and at the bottom an input to enter new messages (basically any text/messaging app you’ve used).

We’d like the message list to scroll to the bottom whenever a new message is added, either by the user or when a new message is received from the server.

Of course DOM manipulation shouldn’t happen in the controller, so we’ll whip up a nice little directive for it. Our screen should look roughly like this:

And our simple controller code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
angular.module('chat').controller('ChatCtrl', function(ChatService) {
  var chat = this;
  chat.addMessage = addMessage;
  activate();

  function activate() {
    ChatService.getMessages().then(function(messages) {
      chat.messages = messages;
    });
  }

  function addMessage(message) {
    chat.messages.push({text: message});
    ChatService.addMessage({text: message});
  }
});
1
2
3
4
5
6
7
<div ng-controller="ChatCtrl as chat">
  <div chat-message-list="chat.messages"></div>
  <form ng-submit="chat.addMessage(chat.newMessage)">
    <input ng-model="chat.newMessage">
    <button type="submit">Send</button>
  </form>
</div>

We have a very basic ChatCtrl that uses a chat list directive. That directive is being passed our list of messages, and it is responsible for displaying that list on screen.

Here’s how we’d implement that directive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
angular.module('chat').directive('chatMessageList', function() {
  return {
    scope: {
      list: '=chatMessageList'
    },

    template: '<div class="js-chat-list">' +
                '<div ng-repeat="message in list">' +
                  '{{message.text}}' +
                '</div>' +
              '</div>',

    link: function(scope, element) {
      scope.$watchCollection('list', function() {
        var $list = $(element).find('.js-chat-list');
        var scrollHeight = $list.prop('scrollHeight');
        $list.animate({scrollTop: scrollHeight}, 500);
      });
    }
  };
});

Full Plunker Example

The Actual Communication

As you can see our directive has an isolated scope: in the directive definition we provide a value for scope and define the different attributes of the scope and how they should be bound.

Using an isolated scope makes it really easy to pass specific “arguments” to our scope and having those arguments be easily bound between the controller and the directive.

Also, isolation makes for more readable and maintainable directives – you immediately see what they expect to receive as inputs in their scope definitions.

This basic use of scopes is a major building block in big Angular apps. It allows us to use directives a bit like functions where we set their input and just have it go off and do some work (e.g. “set and forget”, see what I did there?)

Scroll to Bottom Logic

This is a great use case for using $watchCollection instead of $watch.

Our directive wants to scroll to the bottom whenever a new message is added to the list of messages.

A simple $watch('list', func) would not work, because it’s a shallow watch and our list instance doesn’t change – we only add elements to it.

We could use a deep watch (i.e. $watch('list', func, true) – notice that last true) but that would be wasteful since our messages objects don’t really change – we just add things to the list. That means there’s no real reason to have Angular scan each element for changes – messages themselves are immutable.

$watchCollection is the perfect tool since it just watches the list for additions and removals and doesn’t have a deep watch for every element in it. This, as Goldilocks would say, is “just right”.

The Way Forward

The next parts will be more interesting in my opinion – how should your controller notify your directive of changes? How should the directive notify the controller? Sign up to my newsletter below to get the updates (no spam guarantee or I will spend the rest of my career only doing web in Dojo).

Angular: Watches, Watches Everywhere

| Comments

You can only go so long in your Angular path before starting to learn about performance in Angular and some of its common problems.

You’ve probably heard about “lots of watches” being a problem. But what exactly is a “watch”? Is it just $scope.$watch()? No! Let’s dig in.

What’s in a Watch

A “watch” is Angular’s mechanism for keeping track of a specific expression and acting when it changes. Every watch has the expression that it evaluates on every digest cycle to see if it has changed and also the handler function that gets called whenever the expression’s value has changed.

Not all watches were created equal, especially from a performance perspective. By defaults watches are shallow and so pretty quick. But if, for example, you use a deep watch on a huge list, don’t be surprised if it adds a lag to your app.

The Common Types of Watches

The $watch

Yeah, the obvious case is the one I just mentioned. Whenever you explicitly use $scope.$watch('expr', function() {}) you are adding a watch for the expr expression.

Templates Binding with {{ foo }}

Whenever you use double curly brackets in a template in order to display a value you’ve set in your scope you’re basically adding a watch. This watch will keep track of the value and update the template’s DOM whenever the value changes (after all there’s no magic here – the browser doesn’t know how to bind your expression and the DOM which means Angular has to update things, it’s just hiding those details from you).

While we’re at it, let me add on a side note that just adding things to your $scope doesn’t add a watch. It’s only binding to it in some way that adds it.

Isolated Scope Bindings

When you pass to a directive with an isolated scope something on its scope, that too creates a watch.

For example, if you have a directive whose scope definition looks like this scope: {foo: '='} then Angular will make sure to keep it in sync – if the value changes in your parent scope it will also changed in the directive’s scope. This is achieved by creating a watch for foo that makes sure to update it inside the directive’s scope whenever the value changes in the parent scope.

Attributes in Templates

When you have Angular expressions used inside attributes in your templates, those are usually creating watches too.

Take ng-show and ng-hide as an example you’re probably familiar with. These directives receive an expression and do something depending on whether it evaluates to true or false. This act of tracking the expression’s value is really watching stuff over.

Filters

This is kind of a private case of the previous point, but it’s worth pointing out. Filters keep being evaluated and updated because on every digest, just like any other watch. But they are usually heavier than regular watches and do more complex things, so keep that in mind.

And, Of Course, Code

Along these watches, which are relatively straightforward to find in your code, you should also keep in mind that more watches might be used by the code of other components you may be using.

As an example, our beloved ng-repeat directive is using watches (specifically a $watchCollection) in order to update the list it received whenever changes happen. So even if you don’t see an explicit watch in your template, it doesn’t mean that it’s not there.

Watch Out

So, to sum up this post, as you can see watches are pretty much everywhere in Angular land. Next time you’re looking at the number of watches using ng-stats you should be more equipped to understand how that number came to be.

Angular Performance Diagnosis 101

| Comments

Angular can feel magical but it is not a magic bullet. That magic comes with a cost, and that cost sometimes means slow/laggy apps.

Once you’ve noticed that some parts of your Angular app have performance problems, the hardest part is pinning down what exactly is causing the problem.

Let’s see how you might start tackling this gnarly problem:

First, take a look around your app

Before diving head first into your problem, I find it useful to take a few minutes to roam around my app to get a feel for its behavior all across. This helps realize the scope of your issues and where they are most painful.

Just go ahead and use your app a bit, checking different screens that use different widgets and modules. While doing it try to notice if you see performance differences in certain areas. Also, I find it priceless to do with exploration while having ng-stats open. It’s a super nifty code snippet that lets you easily see how long your digests are taking and the number of watchers currently in your app.

Doing this makes it easier to understand what’s your “baseline” performance – what’s the minimal number of watchers a page has, what is a high number of watchers for you, where are your digests taking too long.

Understanding your performance problem

Now, let’s try and understand what kind of performance problem exactly you’re facing.

Load/initialization vs. general slowness

Is your problem that some view takes too long to load or render? Or is it more an issue that everything feels clunky in that view, e.g. typing in inputs has some delay to it, or clicks feel like they take time to “work”?

Load time problems are, a lot of the time, not Angular specific. For example, if you’re waiting to fetch thousands of elements from the server and then list all those elements on screen, you’re gonna have things be slow sometimes even if you do it in vanilla JavaScript. Face it.

In those situations you should probably look into the general ways we’ve been treating these problems in the web for decades, like pagination (or infinite scrolling, etc.).

But, in case that the overall experience of using your app feels laggy, you might have to do some fine tuning of your Angular code to make it play well with others. Can you see slowness go with long digest cycles or areas with lots of watchers? That’s probably it.

Everywhere vs. specific screens

Is the slowness you’re seeing across the whole app or just in some specific screens, when there’s a certain widget being used, etc.?

If you can say the issue is only in part of your app you’re in good shape. It’s time to start zooming in on that slow part and inspect it to find suspects. Sometimes I just start commenting parts out till the problem goes away – it sounds stupid but a lot of times it helps me pin point the bad parts super quickly.

In cases where the slowness is all around you should look at the more general things: do you have too many things on your root scope causing a lot of watches? Might you be using some widget/plugin/foo that’s adding a lot of cost?

Some potential tricks to make things faster

A few basic tricks that you should probably know once your Angular project gets big enough:

  • If you have a big ng-repeat sometimes adding “track by” can speed things up significantly.
  • If you list is still slow you might want to look into virtualization, like using ui-grid.
  • Minimize the number of watches in general, for example replacing ng-show and ng-hide with ng-if sometimes improves performance noticeably.
  • Reduce the amount of deep watches your perform where possible – can you use regular watches, or $watchCollection etc.?
  • Using events on scopes can be a performance issue in deep scope hierarchies.
  • Reduce the number of watchers by making those watches that don’t change use the bind-once syntax.

Measure twice, optimize once

Most important is to make sure you’re not doing these changes blind. Make sure to measure the effectiveness of your optimizations. You’d be surprised how easy it is to go through a lot of hoops just to realize that you actually didn’t make performance any better (or at least not in a way that makes the optimization worth it).

The easiest way is to get a feel for your improvements by checking it out with ng-stats and similar tools, but the best would probably be to have code that repeatedly calls digest and measures the time it takes in certain scenarios. Some people even create a performance test suite that checks that things aren’t getting too slow over time. I hope to write more about this soon.

That’s it for now. May your digests be always fast!

Angular Performance: ng-show vs ng-if

| Comments

You’ve probably come across ng-if and ng-show and wondered why they both exist and what’s the difference between them. After all they usually have the same behavior as far as the user is concerned.

The devil is in the details and the differences between these directives can allow your to boost your application’s performance easily.

The Differences

Both ng-show and ng-if receive a condition and hide from view the directive’s element in case the condition evaluates to false. The mechanics they use to hide the view, though, are different.

ng-show (and its sibling ng-hide) toggle the appearance of the element by adding the CSS display: none style.

ng-if, on the other hand, actually removes the element from the DOM when the condition is false and only adds the element back once the condition turns true.

Since ng-show leaves the elements alive in the DOM, it means that all of their watch expressions and performance cost are still there even though the user doesn’t see the view at all. In cases where you have a few big views that are toggled with ng-show you might be noticing that things are a bit laggy (like clicking on buttons or typing inside input fields).

If you just replace that ng-show with an ng-if you might witness considerable improvements in the responsiveness of your app because those extra watches are no longer happening.

That’s it: replace ng-show and ng-hide with ng-if!

Caveats and Pitfalls of ng-if

  • Measure, measure, measure: As with every optimization, you should not apply this without measuring and validating that it does speed up your app. It can, potentially, actually make things slower, as I explain below.
  • Your controllers will be rerun: The controllers and directives in the element that’s being removed and added again will actually be recreated and so their initialization logic will run again. This is in contrast to ng-show where things are always there in memory, and so are only initialized once. You need to make sure your code handles being rerun properly.
  • Sometimes initialization is more expensive than keeping things around: That’s to say that in some cases the cost of removing the element from the DOM and then recreating it to add again can be a heavy operation all by itself. In those cases you might feel that it takes too long for the element to reappear. In those cases this trick might actually degrade your app’s performance, so remember to check and measure!

That’s it. Enjoy making your app a bit snappier. If you care about performance in Angular you really should read about speeding ng-repeat with the track by syntax.

Controllers Should Not Be Control Freaks

| Comments

It’s super easy to get baffled about what should you put inside your controllers. Especially if your background is with frameworks touting MVC, you might think that the name “controller” in Angular indicates some kind of control.

The idiom in Angular is to keep your controllers extremely thin. That is the common paradigm, and also the general direction things are going as you can see in this great and common style guide, the introduction of “controller as” syntax and with Angular 2’s upcoming removal of controllers.

Let’s try to make sense of the controllers’ valid responsibilities.

Why keep controllers thin?

First and foremost, writing your code this way results in more maintainable code. When you don’t watch out, controllers tend to become tangled beasts that take on too much responsibility. This makes it extremely hard to test them properly, reuse stuff and is just bad programming as agreed by everyone who’s heared of the Single Responsibility Principle.

Also, I already mentioned that Angular 2.0 is dumping controllers. No, you should not start working in 2.0 now or worry about it too much, but it does make sense to be aware of where things are headed and to start accepting the lessons the Angular community has learned and accepted.

What should not be in controllers?

Getting technical, let’s start with all the things that you should probably not put in your controllers.

  • HTTP stuff: Probably the easiest way to get scolded on an Angular forum these days is to share code that’s performing $http calls directly from your controllers. It has become common practice to hide this inside services as well, even if some Angular documentation has examples doing otherwise. Having a specific service for handling the requests of a certain aspect (e.g. a REST resource) means that you can easily find everyone that’s using it and can make changes in a single place in case the server’s representation of the object changes. Software engineering, who would’ve thought.
  • DOM manipulation: There’s a reason that controllers don’t have access to their element easily. That’s because DOM access is reserved to directives in Angular. You probably know this already, but still.
  • Complex view logic: While controllers are bound to views and end up managing them, if you notice that your logic is become complex you should consider pushing it outside to a specific directive or maybe put some of the logic in a specific service.
  • Model logic: Most controllers are responsible for manipulating/displaying a specific model and tend to take on the responsibility for managing that model. You should take that logic outside of the controller, preferably into a Model object that is a good old object. Yes, even though Angular doesn’t have an angular.model() function it doesn’t mean you can’t still have them. Just create plain JavaScript classes or even use a service to declare the class of your models.
  • Business logic: Business logic is important, changes a lot, and usually will be reused across multiple controllers as your app grows. Because of this it makes a lot of sense to create specific services for the different aspects of your business logic and use them from your controllers. This makes the logic easily testable and reusable.

What should be in controllers?

Controllers with Angular-zen spirit should essentially map actions from the view to the different models and services, with as little logic as possible. Most of your controllers should be basic delegation once they’ve set up the view model on initialization.

In a way, good controllers let go of control!

An example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
angular.module('tasks').controller('TasksCtrl', function($scope, $http) {
    var vm = this;

    function activate() {
        // Bad controller! Don't access $http!
        $http.get('/tasks').then(function(response) {
            $scope.tasks = response.data;
        });

        // Much better - use a service:
        TasksStore.getAll().then(function(tasks) {
            vm.tasks = tasks;
        });
    }

    activate();

    $scope.showDueSoonTasks = function() {
        // Bad controller! This is business logic!
        $scope.tasks = _.filter($scope.tasks, taskDueDateIsIn(2, 'DAYS'));

        // Much better - put the business logic somewhere else
        vm.tasks = TasksPrioritizer.getDueSoon(vm.tasks);
    };

    $scope.snoozeTask = function(task) {
        // Bad controller! Stop reaching into your models!
        if (task.dueDate < now()) {
            task.dueDate = addDate(task.dueDate, 2, 'DAYS');
        }

        // Better - use real models with responsibility:
        task.snooze();
    };
});

Keep (cont)rolling!

Resourceful Angular: $http, $resource and Restangular head to head

| Comments

Probably the most common task you do in your Angular app is making REST requests. You’d think something like this, which is at the core of any SPA, would have a consensus in the community about the Right Way™ to do it.

But actually if you’ve looked around you probably came across multiple camps: those who use $http, those who use $resource and those who use bigger guns like Restangular (there are others, but in this post I’ll focus on it as the most popular one by far).

You probably wondered what are the differences and which should you use. This is a quick summary trying to make sense of those options.

Overview

$http

This is the easy and straightforward route. $http is pretty much what you’d expect it to be and since it’s so raw it means that you’ll probably write more code than you will with the alternatives but have the most flexibility and control. There’s no limitation on what you can do.

It’s also built in with Angular and doesn’t require adding another dependency.

$resource

$resource (also known as ngResource) is Angular’s attempt at supplying a higher level of abstraction over $http. It used to be built in and has been separated to an external dependency. It basically supplies you with a relatively easy way to create objects that perform the different CRUD requests transparently.

I think this example pretty much shows the use case they had in mind, in which we define the User model and show how to update one:

1
2
3
4
5
var User = $resource('/user/:userId', {userId:'@id'});
User.get({userId:123}, function(user) {
  user.abc = true;
  user.$save();
});

$resource’s history has been wonky, as it had a lot of limitations and bugs in earlier versions of Angular and still has documentation and API that are a bit cryptic to master. Usually, if your object model is complicated enough to warrant wrapping $http I’d jump straight to Restangular.

Restangular

Restangular has several differences from $resource, but 2 main ones are that it has a saner API and embraces objects and nested models whole heartedly.

If you have an object model that’s complicated Restangular can be a big help and save you writing a lot of boiler plate code. It also has pretty much every feature you can dream up and great documentation.

Which should you use?

First, I’ll say that IMHO (which seems to be shared by many) $resource isn’t a real player here. You’d either use $http or Restangular.

Now, if you really prefer keeping boiler plate code to a minimum or like the extra abstraction Restangular is quite nice.

I, though, usually prefer reducing dependencies to a minimum and like to have ultimate control. There are a few little issues with Restangular that together boil up to make me rather just go with $http most of the time:

  • It’s an extra dependency. That means more time to load my app, more stuff to learn and more stuff to manage.
  • I don’t like the idea of having “special objects” floating around. It means that if you have services that handle models they can’t necessarily treat all objects the same – if the object was fetched over the network it’s “restangularized” and has extra stuff, if you just created it in the client and haven’t saved it yet it behaves a bit differently.
  • It makes it harder to spot where a certain endpoint is being used. If you use $http to create a service responsible for operating on a specific model you can easily find all the calls for a specific endpoint easily. For example, say your app has Projects, which have users, and Tasks, which have users. If at some point we want to rename task’s “users” to “assignees” you’ll have a hard time going over every getList('users') in the code to see if it’s a project or a task. With services I’d probably just change the TasksStore.getUsers() function.
  • Restangular’s nested objects that return more and more objects make testing cumbersome. It’s harder to mock out a certain dependency since you end up having to create mocks that return more mocks. This is a matter of taste, but I usually look at this as a code smell (a-la the Gary Bernhardt school of thought).

So, yes, I prefer $http, but for some people Restangular “clicks”, and that’s awesome. Just stay away from $resource.

Happy ajaxing!

My Angular Debugging Tips

| Comments

Yeah, I know, your code is awesome and you never write any bugs. My code does have bugs every now and then. In those cases these tips come in handy.

ng-Inspect Element

Perhaps the most useful trick is to know that once you right click on an element on screen and pick ‘inspect element’ Angular makes it very easy for you to get things going.

In the browser’s developer tools console write angular.element($0) and you now have access to all the good things:

  • Scope: angular.element($0).scope() will return the scope for the element. This is golden.
  • Controller: angular.element($0).controller() will give you the controller, doh.
  • Injector: angular.element($0).injector() returns the app’s injector, which you can then use to get access to other things (e.g. injector.get('MyService') or injector.get('$http'))

Extensions

There’s a growing number of handy extensions and snippets for Angular. Here are a few ones to try out:

  • Batarang – An official extension from Angular itself that most people love just because it shortens the previous trick from angular.element($0).scope() to $scope and the likes.
  • ng-inspector – Has similar tools to Batarang’s for looking at your app’s hierarchy, walking the scopes, etc. but works on Safari and Firefox and not just Chrome.
  • ng-stats – A little utility to show your app’s digest/watches situation, handy for spotting performance issues.

Print debugging

Print debugging is always useful, but sometimes console.logs alone are not enough. For these cases Angular provides us with a very nice little filter that even the docs say is just for debugging – the json filter.

Have some model or scope you want to see easily? Just print it: <pre>{{ someModel | json }}</pre> (Using pre means you’ll see the json properly formatted).

Bugs be gone

I hope this will help you out. If you have any other tricks I’d love to hear!

Happy debugging (well, you know, as much as possible).

Should You Use Angular 2.0 or 1.x?

| Comments

This question might seem trivial, but I keep seeing it pop up again and again everywhere in the Angular community. With all respect to the maintainers, they’ve managed to confuse quite a lot of smart people with this.

If you’re new to this world and want to get started with a new project you might have wondered whether you should use 1.x or “jump straight” to Angular 2. On the other hand, if you’ve already got Angular experience you’re probably getting worried about the impending changes and wondered whether you should start adapting to it.

And those are valid questions. After all, what are you supposed to think when every newsletter and forum are filled with articles about Angular 2’s forms, architecture, new router, Typescript, etc.? Why would the community push out so many articles about writing simple apps in Angular 2 if it shouldn’t be used?

The executive summary: There’s no Angular 2 to use, so Angular 1 is still the way to go.

A bit more details

Angular 2 is getting a lot of hype and attention, but the reality is that it is still in alpha and changes quite rapidly. It is not intended at all to be used in production yet. So, really, you can’t and shouldn’t start your company’s next big project using it.

So what’s up with all the articles? It’s a combination of a lot of things.

First, people are excited because Angular 2 brings a lot of nice stuff, and so they start exploring it and writing about the benefits.

Furthermore, it is impossible to be in this community and not hear people mumble about the Angular 2 migration that “will break all our code”. This motivates a lot of people to start learning 2.0 to see what is awaiting us and start understanding what’s going on.

Also, because it’s still heavily under development, writing about its current state and complaining about things actually might change things for the better as opposed to the general useless complaining we’re used to on the internet. It is a rare opportunity to affect technology you might be using for years to come.

All this is just to say that while Angular 2 is getting a lot of hype (and probably will get even more before it’ll be out), it is not production ready. If you have the time or freedom and find it interesting, of course you should give it a try, and even if you don’t have time it’s probably a good idea to keep up with the news and reading material. Eventually, the migration path will start getting clearer and when it does you’ll probably want to know as early as possible what you should be changing.

How will you know when to it’s time to start seriously looking at Angular 2?

If you’re reading this post, I’m assuming you read the news every once in a while. So just make sure to keep doing it. There are plenty of communities and newsletters (cough like the one here on my blog cough) you can trust to update you.

Happy Angularing!