codelord.net

Code, Angular, iOS and more by Aviv Ben-Yosef

Directives are not what they were a year ago

| Comments

Since the very early days of Angular, directives have been one of the gnarliest pieces to grok and wrap your head around.

There have been countless of posts on forums and groups asking what exactly are directives and what should they be used for? And thousands of words were published trying to answer these questions.

But, most of those no longer hold true. If you’re just getting into Angular 1.x, most of what you’ll find online about the role of directives is outdated.

And if, on the other hand, you’ve been doing Angular for quite some time now, then you should know that things have changed. The community is flowing in a different direction, and you should get with it (or at least know what you’re missing out on).

The “old” thinking behind directives

In the first version of Angular, controllers were held as a very big part of the framework where most of the logic would lie.

Directives, it was commonly said, should be used only for DOM manipulation or for reusable components.

When learning Angular, you’d be told that you can wait with learning about directives, since you rarely write ones yourself. After all, with the awesomeness of Angular you don’t need to reach your hands down to the DOM on a daily basis.

And, really, how many reusable components do you write in a given week?

The new standard – directives and components for ALL THE THINGS

Over the past year, Angular 2 has matured and the migration path to it is getting clearer. With that, the Angular team have been moving Angular 1.x towards these new concepts.

We know that controllers are gone in Angular 2, and you should be killing yours.

The old/new stars are directives, mostly in their fancy new cloths as components.

I’ve written before about what components are and how you should use them. 90% of the time you should be able to use a component instead of writing a directive.

And you should basically no longer be writing any controllers that are not directive-controllers or component-controllers.

Yes, even if that directive is not reusable at all and will only be used in a single place. And even though there’s no DOM manipulation going one.

The world is changed. Do not shy away from directives. Nowadays, Angular consists of UI code in directives/components and logic in services. That’s it.

What to use directives/components for

  • Pages
  • Reusable components
  • DOM manipulation
  • Wrapping up non-Angular widgets
  • Non-reusable components (e.g. just breaking up a bigger component to smaller pieces)
  • Routes

Basically, the rule of thumb is: don’t use controllers, put logic in services, everything else is in components.


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Angular Performance: Updating bind-once elements

| Comments

Performance can be tricky with Angular. It’s quite easy to have a page that’s slow or unresponsive because you got too many watchers going on.

Angular 1.3 shipped with the new bind-once syntax, but I hardly see people use it. Even if you add it, you hardly never want things to never change again.

Usually, you have a bunch of stuff that change together. Plainly using bind-once would remove all the watches and make your page responsive and your digest cycles fast. But, how would you go about updating it?

It’s a bit tricky, but doable. In this post we’ll show an example of performing such an optimization.

Our use case: search results

Let’s say you have a page in your app that let’s you search something. You get from the server a response with 100 items that you them display:

1
2
3
<div ng-repeat="item in $ctrl.results">
  <div>{{ item.name }} - {{ item.description }}</div>
</div>

If we display 100 results at once we already have 200 watches: 2 bindings (name and description) per item displayed.

This can easily get out of hand.

But look at your results. They’re not going to change individually. The will only change as a whole, when, for example, the user goes to the next page or types a different search query.

Let’s get rid of them watches!

Binding once

You might first start with something trivial like this:

1
2
3
<div ng-repeat="item in $ctrl.results">
  <div>{{ ::item.name }} - {{ ::item.description }}</div>
</div>

This simple change (adding :: in two places) rids us of those 200 watches. Yay!

But, what would happen if you now update the description of items inside $ctrl.results, e.g. because the user marked them as read?

Nothing.

It’s a bit crappy that there’s no easy way to tell Angular to refresh these bind-once expressions.

But don’t give up yet.

Note: In this example, if you add/remove elements from $ctrl.results they will be added/removed to the ng-repeat. If you never change the inline elements you wouldn’t need anything more than this. This is a simple example, but pages with performance problems usually aren’t simple :)

Forcing an update of bound-once content

This requires a bit of coding. Basically, we want to tell Angular to throw away those frozen elements and recompile stuff to use our new content.

Our end result would look like this:

1
2
3
4
5
<refresher condition="$ctrl.lastUpdate">
  <div ng-repeat="item in $ctrl.results">
    <div>{{ ::item.name }} - {{ ::item.description }}</div>
  </div>
</refresher>

We wrap our content with a specially crafted directive, refresher. This directive listens for a given property. Once that property changes its value, refresher recompiles the content inside it.

This means that we effectively have a single watch active, and once that watch’s value changes everything updates.

In our case, we can have lastUpdate be whatever you want as long as it is updated when your content changes. I usually just use a timestamp that I update whenever the content changes.

Here’s how refresher looks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
app.directive('refresher', function() {
  return {
    transclude: true,
    controller: function($scope, $transclude,
                         $attrs, $element) {
      var childScope;

      $scope.$watch($attrs.condition, function(value) {
        $element.empty();
        if (childScope) {
          childScope.$destroy();
          childScope = null;
        }

        $transclude(function(clone, newScope) {
          childScope = newScope;
          $element.append(clone);
        });
      });
    }
  };
});

There’s not a lot of code going on around here.

refresher is a basic directive (why not a component? because components have to have isolated scopes, which I don’t want in this case).

This directive basically watches for changes in the value of whatever you pass to its condition attribute.

Whenever that value changes, refresher throws out whatever it previously contained and recompiles things, so they’ll appear on screen updated.

This is a basic example of using the $transclude service manually.

That’s it!


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Angular 1.5 new component lifecycle hooks

| Comments

It’s only been 2.5 months since Angular 1.5 came out, introducing components. Most companies haven’t even had the chance to upgrade yet. Yet, in the mean time, the Angular team released 3 more releases.

With 1.5.3 components have become a bit smarter and a bit more compatible with Angular 2. This new version introduced some new and useful lifecycle hooks to directive/component controllers. Let’s take a deeper look at how these can help you write cleaner code!

Recap: $onInit

I’ve previously written on $onInit, the first lifecycle hook introduced with version 1.5.

It provides you with a nice and clean place to initialize your component after all of its bindings have been set.

This roughly maps to Angular 2’s ngOnInit.

New: $onChanges

This new hook is similar to ng2’s ngOnChanges. It is called whenever one way bindings are updated, with a hash containing the changes objects.

Prior to this hook you sometimes had to use a $watch in order to do some work whenever a value you’re bound to changes. Using this hook makes things clearer and removes the need to introduce a watch and a dependency on $scope.

New: $onDestroy

A hook that gets called whenever the controller’s scope is being destroyed.

Whenever you used external resources, or add DOM listeners, in your component you’d (hopefully) use $scope.$on('$destroy', ...) in order to clean up when your component would get destroyed.

This hook, similarly to $onChanges, makes things simpler and saves us a dependency on $scope.

Unsurprisingly, this is equivalent to ng2’s ngOnDestroy.

New: $postLink

This isn’t something that comes up often, but maybe you got bitten in the past by the difference between a directive’s link function and the directive controller’s function.

These two do not run at the same time: the former runs after the DOM is ready while the latter isn’t.

This means that for some DOM manipulation and operations you had to work harder in order to perform it in a component (or maybe you had to use a directive).

Now we can use $postLink and know that all of our child components are ready. This, together with the $element injectable we have in components makes it even less likely that you’ll need to write an old-style directive. w00t!


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Please leave the ng prefix alone

| Comments

This might be obvious to the Angular veterans here, but I keep coming across this. Every time that I go through a new Angular codebase I find at least one directive or service that uses the ng prefix in its name.

And really, we can’t blame people for doing this since when you’re just starting with Angular use keep seeing ng-this and ng-that. How is a newcomer supposed to know any better?

But please, stop. And if you have any of these remaining in your codebase, take an hour and rename it, for the love of all that is holy.

The ng prefix is reserved for Angular’s own stuff

Yes, it’s theirs. And we’re lucky they use a prefix, because it makes it easier to spot what is part of the standard library and what isn’t.

At least, it’s easy as long as you don’t shove your own stuff there.

There also so many default directives that there’s no chance you know all of them and it’s very easy to clash with some existing stuff. So please don’t.

There are open source libraries that still misuse the prefix, but the numbers are dwindling.

A very prominent example is ng-grid which has been renamed to ui-grid.

You don’t even have to use a prefix

I’ve seen lots of projects (not libraries) that do just fine without prefixes. But even if you decide to use one, just pick a different one. Here, you can use fj. It’s easy to type. Have a blast!


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Naming Your Controller-As Consistently

| Comments

Conventions have always been a problematic part of Angular, especially when they seem to change all the time.

A very common issue that I’ve been asked about again and again is what name to use in controller-as.

Here are my 2 cents on a style that, to me, makes the most sense.

First, understand that the options basically divide to either using the same name in all your components/directives, or to use a specific name in each.

I strongly recommend to use the same name in all templates. It means less typing, less thinking about boring details and of course means easier refactoring down the road.

Now, the question is what name should you use. Prior to Angular 1.5, the community seems to have settled on “vm” as the name (e.g. that’s the default in John Papa’s style guide).

But, with the introduction of components in 1.5 the default there is now “$ctrl”. Even though I personally dislike the look of $ctrl I have to recommend sticking to it. It is only a matter of time before this becomes the de-facto standard as the community upgrades to 1.5.

What about referencing parent controllers??

One of the arguments I’ve heard quite a bit for using a different name in each directive/component is so it will be possible to reference parent controllers in the scope.

But, you should never do that. Your scopes should virtually always be isolated, so that name clashing would be impossible.

And in the (truly) rare occasion where you do reference some parent controller you should do it using the require mechanism.


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Using Angular 1.5’s Multiple Transclusion Slots

| Comments

Most (well maintained) Angular projects eventually reach the point where they would benefit from having a few generic components that use transclusion.

Maybe you have a timeline feed screen with multiple types of feed items.
Or some tabs widget.
Or a generic modal you use across the app.

Transclusion allows us to create very customizable components since you can inject them with other components, and not just pass rigid inputs (e.g. specific bindings). That’s pretty much how things like ng-repeat work: you provide those directives with inner HTML that they then use.

Prior to Angular 1.5 a component could only transclude a single entry: whatever you gave it was had to be used as a whole.

But, among other goodies introduced in 1.5 we also got multiple slot transclusion, which comes in handy at times.

Example

Say you want to create a generic modal, that can have both the title and body customized.

Here’s an example of someone using the modal component we’ll create:

1
2
3
4
5
6
<modal>
  <modal-title>Are you sure ?</modal-title>
  <modal-body>
    You can only do this  times
  </modal-body>
</modal>

Those modal-title and modal-body elements are the transclusion slots we will now define and use in our modal component:

1
2
3
4
5
6
7
8
9
10
11
12
13
app.component('modal', {
  template: [
      '<div ng-transclude="title"></div>',
      '<div ng-transclude="body"></div>'
  ].join(''),
  transclude: {
    title: 'modalTitle',
    body: 'modalBody'
  },
  controller: function() {
    // Stuff to make this component render as a modal
  }
});

As you can see above, we define the component’s transclude property to have 2 slots, named title and body.

Each slot also has the name of the element it expects to see its content inside.

Then in the component’s template we can decide where to insert the transcluded elements by using the ng-transclude directive and supplying it with the slot’s name.

As you can see transclusion automatically takes care of things like passing the scopes correctly so that even though the templates we passed reference the original component’s scope ($ctrl), it’s still properly visible inside.


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

What is the Component Router? Can you start using it?

| Comments

A new router for Angular 1.x was announced over a year ago. That router is usually called the Component Router, but you may have seen the name “new router” (or ngNewRouter) thrown around.

Its release keeps getting delayed. Documentation is scarce. The GitHub repo is abandoned.

I keep seeing people wondering whether they should be using it and how. Let’s try and answer those concerns.

What is different about it?

The component router is aimed to make routing easier in a world of components, like the awesome ones we got in 1.5.

It has some similarities to the Angular 2 router.

The component router also incorporates some features that have long been considered a standard in ui-router, such as nested routes.

The gist is that you define a root component – that’s the component that starts all your app’s rendering.

In it you render sub-routes using an outlet (<ng-outlet></ng-outlet>), much like the old ng-view or ui-router’s ui-view.

But, you can keep on nesting these outlets, which isn’t possible with ng-view.

You can read more in the design doc.

Can you start using it?

Well, it hasn’t been released yet, but according to the Angular weekly meeting notes it should be out very soon.

I wouldn’t start writing code in it just yet, but you should definitely spend a few minutes reading the code of this demo by one of the Angular core maintainers.

And if you really want to play with it, that demo is a good starting point.

Once it’ll be out officially (hopefully in a couple of weeks) check this space for more information on using it and migrating your existing apps to it.


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Writing Pragmatic Angular Components

| Comments

Angular 1.5’s new components are awesome. But, as with anything new, we’re still learning, as a community, how to best use it.

There are so many different ways to use them. And the style guides aren’t clear yet.

Here are my initial thoughts/guidelines after playing with components lately:

Default to use one-way bindings

Angular 1.5 introduced one-way bindings, as opposed to the regular two-way bindings.

Since the need to override something from a child components to its parent is rare (and perhaps even a code smell), I prefer to always use one way bindings.

So make sure to pass write your bindings like so: {someBinding: '<'}, making sure to pass '<' instead of '='.

Use $onInit to initialize your component

Yes, you don’t have to use to for setting up your component. We’ve been doing just fine without it so far.

But, I think it helps makes thing clearer and explicit.

So, in your component’s controller function put all the setup code inside $onInit, e.g.:

1
2
3
4
5
6
7
8
9
10
11
12
app.component('foo', {
  controller: function() {
    var self = this;
    self.$onInit = function() {
      // Initialize here:
      self.foos = [1, 2, 3];
    }

    // Add the other functions...
    self.addFoo = function() {};
  }
});

Use require to pass dependencies between components layers

2 years ago I wrote about the benefits of using the require feature for making more maintainable and robust directives.

Now, that components have even simpler require syntax and support, there’s really no reason not to use it.

It’s a great way to pass along dependencies between your components hierarchy without having to pass bindings from parent to child, layer after layer.

If you have some top level components that exposes something you need in some grandchild component, instead of using bindings just require it from the grandchild.

It makes these dependencies explicit and also is safer for refactoring, since Angular will let you know if something you’re requiring isn’t here.

Feel free to inject $element to your component controllers

Components aren’t controllers. Components are better directives.

Just because components don’t have a link function, it doesn’t mean you can’t use them for writing something that needs to play with the DOM a bit.

A component’s controller can be injected with $element, just like you get in a directive’s link. There’s a reason it’s there – use it.

Yes, it was taboo to do DOM manipulation in controllers, but that’s the old Angular.

Embrace components and fear not having a true component that has control over its element.


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Learn how to upgrade your Angular 1 app easily, step by step!

Angular 2 migration: what’s ng-forward?

| Comments

Angular 2 keeps getting closer (beta2 was just released). This means everyone are getting more anxious and worried about the future of their Angular 1 code.

The migration path keeps getting clearer. I’ve shown before how easy it is to start integrating ng2 in your existing apps with ng-ugprade.

Yet I keep seeing developers confused ng-forward: Is it the same as ng-upgrade? Is it a formal part of the migration path? When should you use it?

This post will give you the background you need to wrap your head around ng-forward and whether or not you should be using it.

What’s ng-forward

ng-forward is an open source project that aims to let you write Angular 1 code that looks very similar to Angular 2. You don’t actually start to use ng2. Instead, you’re getting familiar with the syntax and a lot of your code will look almost exactly like it would have looked in ng2.

ng-forward isn’t by the Angular core team per se. It is created by the community, but with a blessing of the core team.

Here’s how a simple service would look like when written with ng-forward:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Injectable, Inject } from 'ng-forward';

@Injectable()
@Inject('$q', '$timeout')
class TestService {
  constructor($q, $timeout) {
    this.$q = $q;
    this.$timeout = $timeout;
  }

  getValue() {
    return this.$q(resolve => {
      this.$timeout(() => resolve('Value'), 3000);
    });
  }
}

As you can see, it’s much alike Angular 2, but of course we’re still making use of Angular 1 services like $q.

What’s the difference between it and ng-upgrade

ng-upgrade, which is an official part of the migration path and comes bundled with Angular 2 for now, is a mechanism to run actual Angular 2 code alongside Angular 1.

This means that while with ng-forward you’re writing services that look like Angular 2, with ng-upgrade you write actual Angular 2 services.

If you’re interested in learning more about using ng-upgrade to move your existing code to Angular 2, and learning Angular 2 in general, subscribe to my newsletter and get more posts like these:

Don’t let your Angular 1 app become legacy, learn how to upgrade it!

When should you use it

First of all, I’ll mention that ng-forward doesn’t support ES5 (yet), so you can only use it if you want to use ES6/TypeScript.

This is a big advantage of ng-upgrade: it works with ES5 (though documentation is still lacking) so you can start using it in ES5 project without making a lot of infrastructure changes.

Now, the decision of whether to use it or not boils down to personal preference. They’ve done a marvelous job of making a lot of the syntax closely resemble ng2’s.

If you don’t expect to actually start learning and migrating to ng2 in the near months after its release, ng-forward is an interesting compromise.

You can start getting used to Angular 2 syntax, and won’t have to relearn a lot of things just yet.

Just as with ng-upgrade, there’s no need to rewrite all your code, you can decide to simply write new code with it or migrate specific services/components as it suits you.

Personally, I think that if you can take the hit of bundling Angular 1 and 2 together (which is a bump in download size), you should lean towards ng-upgrade.

Yes, it will take more time (since you’ll have to learn Angular 2), but whatever code you change/write won’t have to be migrated again later.

Also, I find the almost-exact-same-syntax a bit of a disadvantage. Imagine a big project that’s written with ng-forward and that later starts an ng-upgrade migration.

It could easily become confusing to debug and make changes in a code base where neighboring files look very similar yet use a fundamentally different framework underneath.

That said, you should definitely consider using ng-forward if for some reason you won’t be adding ng-upgrade soon.

The sooner you start adjusting the easier it will be down the migration road (or path).


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Don’t let your Angular 1 app become legacy, learn how to upgrade it!

Caching HTTP results in Angular

| Comments

A lot of the work of web developers eventually boils down to making things smoother or nicer for the user.

HTTP calls are a big part of this mess. Web development is async. That means the users perceive slowness.

Say you’re using Trello and go back and forth between a couple of cards. Should you wait every time you click a card for it to be fetched again if it wasn’t changed?

Certainly not.

And while caching isn’t that hard to do, it’s a bit tricky to do right. Let’s take a look.

Note: I’m going to show you how to roll your own caching. In case you have no need of advanced uses, like invalidating the cache or manually changing it for performance optimizations, you might be able to simply use $http’s built in cache option.

Setting things up

Let’s say we’re going to put a cache behind our FooService. To have things work smoothly, you should make sure that you’re not returning $http promises from FooService.

$http promises has the deprecated .success function on it, which you really shouldn’t be using.

Our Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module.factory('FooService',
     function($http, $cacheFactory, $q) {
  var cache = $cacheFactory(
        'fooCache', {capacity: 100}); // 1
  return {
    getFoo: function(id) {
      if (cache.get(id)) {
        return cache.get(id); // 2
      }

      var promise = $http.get('/foo/' + id).then(
        function(response) {
          cache.put(id, $q.when(response.data)); // 4
          return response.data;
        }
      );
      cache.put(id, promise); // 3
      return promise;
    }
  };
});

Note: While this is still an Angular 1 service, you should really consider writing your new services in Angular 2 like I describe here.
And this is a good time to mention that if you’re worried about the future of your Angular 1 app you should subscribe and get my guides for upgrading your app step by step!

Don’t let your Angular 1 app become legacy, learn how to upgrade it!

So, what are we looking at?

At 1 you can see that we use Angular’s $cacheFactory. This is a pretty basic object that behaves much like a regular dictionary/map/object.

But, it has the added benefit that you can specify a capacity for the max amount of items it saves. That easily turns it into an LRU cache.

Then, 2, when we are requested to get a certain value we first try to return it from the cache.

If we find nothing in the cache we make the request, store its promise in the cache (3) and return it.

And, finally, once the request returns we update the cache with the returned value (4).

Note that the cache holds promises, not the actual values. This is for an edge case: it is possible to get 2 requests for the same object before our first request completed.

In that case, we’d rather not make 2 requests. That’s why right when we create an initial request we already store its promise in the cache.

That way once a request has been made we’ll always have something to return and won’t make a request that’s not needed.

That’s it!

Yeah, you’ll probably need to add some more lifecycle management, like invalidating objects that have changed.

But, this is the gist of it.


Do you have a big Angular 1.x app that you’re scared will rot and become legacy code? Because 2.0 and TypeScript will soon be the new shiny yet you have all this JS code sitting there? Where will your team find the time, and management approval, to learn and move things to 2.0?

But what if you could migrate your project, incrementally, while keeping your time’s pace and shipping awesome code? What if your team could learn a bit more Angular 2 with each task? Imagine you could get to be working in 2.0 land without ever stopping your development!

I’m cooking up a self-served course that will get you there. It will allow you, on your own pace, learn Angular 2 and TypeScript bit by bit. With those steps your team will migrate your project and soon you’ll write all your new code with Angular 2, TypeScript, and won’t have to stay behind.

Sign up to be notified when the course is ready (and get more of these pragmatic Angular posts in the meantime).

Don’t let your Angular 1 app become legacy, learn how to upgrade it!