codelord.net

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

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!

Setting up SEO in an Angular app

| Comments

Angular and SEO don’t really go well together without some nudging.

As you probably know, the whole client-side MVC thing has its perks. But, it comes with a price: search engines usually won’t be able to scrape your site.

Angular 2 should enable us to render pages on the server as well, which will help solve this. In the meantime, let us see what you can do with your production app today.

I’ll talk about setting this up using the awesome Prerender.io service, which I’ve had great experience with. It’s also open source, so you can host it yourself if that floats your boat.

We basically set up our site so that requests from search engines get redirected to a Prerender.io server, which then serves cached content to the search engine. Magic!

Note: SEO is not a client-side only deal. You will have to make changes to whatever server you’re using to serve your app. Also, Google has officially deprecated this sort of solution on the grounds that their bots can crawl JS sites. It might be good for you, but if you look around you’ll see plenty of developers complain that it’s not perfect, not working or that they care about more than just Google’s bots.

Site preparation

While it doesn’t take a lot of changes usually, there are still some things you need to make sure you’re doing correctly before SEO will work for you.

Push-state

HTML5 push state makes your app use URLs that look “regular”, e.g. example.com/foo/bar instead of the default example.com#/foo/bar. When doing SEO, my opinion is that using push-state makes things simpler all-around.

If you’re not already using it, you can see my post about getting started with push state in Angular.

Then make sure to add this meta tag (see here why):

<meta name="fragment" content="!">

title, description, and metadata

A lot of the time when writing a simple SPA we tend to neglect the good old <title> tag (and similar tags, like meta description).

We want search engine results to show properly the content the user will find on the page, and so you should make sure to keep these updated.

For example, if you’re writing a forum, make sure to update the title tag to the current thread’s title whenever routing to a new thread.

It’s not really complicated. You should put a directive on the <title> tag that updates it according to the current page.

Pitfall: make sure you have your ng-app on the <html> tag and not the <body>, so you will be able to have directives in the <head> element as well.

ng-click pitfalls, e.g. paging

With SPAs it’s easy to get used to doing most of everything with ng-clicks on elements.

That’s not how plain sites work, right? You should use <a href=“..”> tags to move between states.

Keep in mind that search engine crawlers crawl your site by looking for links. That means that if, for example, you have several pages you’d like it to crawl, you need to use real links.

Instead of having something like <button ng-click="paging.next()">Next</button> that changes the current route to /pages/2 or whatever, change it to something along these lines:

<a ng-href="paging.urlForNextPage()">Next</a>

Setting up Prerender.io

This is actually quite straightforward. Follow these instructions and you should have something running locally in 10 minutes.

Tweaking: Optional API

Prerender.io does a pretty good job of knowing when your site has finished loading before caching it.

But, you might want to tweak it if you’re doing something complicated on page load. They have a little trick you can use to hint them, see here.

You can also look at that link to see how you can return proper HTTP status codes, like 404, in case the crawler tries scraping something it shouldn’t.

You’re good to go!

Go over the prerendered site and make sure all your links work so that the crawlers can get to all the pages you want them to. If all looks good you can go live.


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).

Let me know when that Stairway to Angular 2.0 Heaven course is ready!

Adding the first Angular 2 component to your Angular 1 app

| Comments

In my previous post we saw how easy it can be to add your first Angular 2 service to an existing Angular 1 app, using ES5. This lets you easily have Angular 1 code live alongside Angular 2 code.

This time, let’s start dipping our toes in the real deal: adding your first component.

What’s an Angular 2 component?

A component is a piece of logic (like Angular 1’s controllers) that’s coupled with a view. It’s self contained and isolated. And it can have bounded inputs and outputs.

Sounds familiar? That’s basically Angular 1.5’s .component (see here).

Setting things up

Set up takes a few minutes to add the Angular 2 dependencies and create the upgrade adapter that wires everything together. Follow the instructions from my previous post.

Our shiny new component

We’ll start from a pretty basic component. It will have a single input: that’s ng2 speak for a bounded property, except the binding is not two-way by default.

If we were to write this component in ng1 it would look something like this:

1
2
3
4
angular.module('app').component('greeter', {
  bindings: {name: '='},
  template: '<span>Hello, {{greeter.name}}!</span>'
});

Here it is in Angular 2 and ES5:

1
2
3
4
5
6
7
8
9
10
11
12
13
var GreeterComponent = ng.core.
  Component({
    selector: 'greeter',
    template: '<span>Hello, {{name}}!</span>',
    inputs: ['name']
  }).
  Class({
    constructor: function() {}
  });

 angular.module('app').directive(
    'greeter',
    upgradeAdapter.downgradeNg2Component(GreeterComponent));

Breaking it down

It takes some more lines to write it, but this is essentially the same component we saw earlier.

In Angular 2 we provide a selector to components, but it’s actually not used when using it from Angular 1. All that matters is the name we provide in the .directive() call.

Note that we’re defining the inputs, much like the bindings above.

Using it from Angular 1

When using the upgrade adapter, we still have to use the new template syntax when using the component:

1
<greeter [name]="name"></greeter>

Those brackets mean we’re setting up one way binding to pass the name parameter down to the component and it will be updated automatically whenever you change it in your Angular 1 code.

That’s it!

Where to go from here

You can read more on the upgrade guide, though it’s all in TypeScript for now.

There’s plenty more to go into here: the new template syntax, binding for changes (i.e. outputs), and more.

I’ll be covering more upgrade steps soon, sign up below to stay posted!

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

Adding the first Angular 2 service to your Angular 1 app

| Comments

The Angular 2 beta was released a couple of weeks ago.
We all want to be in the loop and not have our projects stay behind and become outdated.
You know that you should probably spend more time learning about ng2 and what that means for your project.

And Angular 2 comes with a huge set of new technologies to learn and problems to solve:

Should you migrate your project to ES6?
Should you migrate it to TypeScript?
What is the right way to address such a big move, if at all?

Well, we can’t answer all these questions in one post. For today, let’s look into adding your first Angular 2 service into your existing Angular 1 app.

Wait, what about all the rest?

You want to know what language should you use. And whether or not you should migrate your old code. And why are we starting with a service instead of something more sexy like a component, with a view and all?

Slow your roll. Starting with a service is a great way to take one baby step towards Angular 2. We don’t want to take on more than we can handle.

If you’re interested in getting these questions answered, now is a great time to subscribe to my newsletter and get the next parts!

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

The service we will be replacing

Say that you just got a task to introduce a new service. The service is responsible for fetching some REST objects and returning them.

If we were to do it in Angular 1, it would probably look like this:

1
2
3
4
5
6
7
8
9
10
11
module.factory('FooService', function($http) {
  return {
    getFoo: function() {
      return $http.get('/foos').then(
        function(response) {
          return response.data;
        }
      );
    }
  };
});

That’s quite a straightforward service, right?

Adding Angular 2 to your existing project

Note about using ES5: Because we’re using ES5 and not ES6/TypeScript, some code needs extra boilerplate. It’s not that bad actually, and I’m sure you’ll be able to follow along. But I won’t be explaining every single character today (deep dives will be posted in the future, stay tuned!).

Bye bye ng-app

In case your app is currently bootstrapped using the ng-app directive, you need to change it. Angular can be bootstrapped with either ng-app or the manual way of calling bootstrap yourself. In Angular 2 we have to use the latter.

If you have <body ng-app="app"> you’ll need to remove the ng-app bit and add this to JavaScript code:

1
2
3
angular.element(document.body).ready(function() {
  angular.bootstrap(document.body, ['app']);
});

This is actually a pure refactoring, nothing should have changed by this point – refresh to make sure!

Adding the source files

Now we’ll need to grab Angular 2, and its dependency Rx.js, to include them in our project.

Get them however you usually get dependencies. With npm it would look like this:

npm install angular2@2.0.0-beta.0 rxjs@5.0.0-beta.0

And then add this to your index.html file:

1
2
3
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-all.umd.dev.js"></script>

Introducing UpgradeAdapter

When I wrote about the Angular 2 migration path, I mentioned the ngUpgrade library which will be used to supply us with the ability to run Angular 1 code side by side with Angular 2 code.

With time this has basically become the UpgradeAdapter you can find in Angular 2.

We will create an instance of this adapter and use it to bootstrap our app. This initializes our app as a hybrid app that can use both Angulars.

Let’s change the bootstrap code from above to look like this:

1
2
3
4
var upgradeAdapter = new ng.upgrade.UpgradeAdapter();
angular.element(document.body).ready(function() {
  upgradeAdapter.bootstrap(document.body, ['app']);
});

Tip: you’re used to using angular. for accessing Angular 1 stuff. Angular 2 exposes all of its shiny stuff under the ng global.

That’s it, we’ve successfully included Angular 2 in our app. Refresh to make sure everything looks ok!

Writing our new service

In Angular 2 services are essentially just plain classes. Because ES5 doesn’t have classes really, we’ll use the nice wrapper Angular 2 supplies us with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upgradeAdapter.addProvider(ng.http.HTTP_PROVIDERS); // 1

var FooService = ng.core.
  Injectable().
  Class({
    constructor: [ng.http.Http, function(http) { // 2
      this.http = http;
    }],
    getFoo: function() {
      return this.http.get('/foos').map(
        function(res) { return res.json(); }
      ).toPromise(); // 3
    }
  });

This might take a bit of getting used to.

First, at (1), we tell the upgrade provider what kind of Angular 2 dependencies our app requires. In this case it’s the HTTP library.

Then in (2) we define our service’s class and inject it the Http instance. This is a bit like injecting $http in Angular 1, except we provide the actual constructor/type of our dependency, not just a name.

And finally we just execute the AJAX request, similar to Angular 1. Note that Angular 2 works with Observables instead of promises, but observables have a toPromise() method that we use (3) in order to supply the same interface to our Angular 1 code.

Using our new service in Angular 1 code

First, let’s expose this service to our Angular 1 code:

1
2
3
4
upgradeAdapter.addProvider(FooService);
angular.module('app').factory(
  'FooService',
  upgradeAdapter.downgradeNg2Provider(FooService));

And now we can use this service as we would use any other service:

1
2
3
4
5
6
7
8
9
10
11
angular.module('app').component('foo', {
  templateUrl: 'foo.html',
  controller: function(FooService) {
    var vm = this;
    FooService.getFoo().then(
      function(foos) {
        vm.foos = foos;
      }
    );
  }
});

Victory!

Yeah, that’s it. You have a new skill and just added your first real Angular 2 code to your existing app.

Yes, there’s plenty more to do. You might want to use components. Or use Angular 1 code inside your Angular 2 code. Or write your new stuff in TypeScript.

We’ll get there. Be sure to sign up below to get it :)

For now, you can take read the official upgrade guide (TypeScript only), and Dave Ceddia’s great blog.

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

Automatically find links in text using Angular

| Comments

There comes in every web developer’s life a day where he needs to take some block of text and automatically find URLs inside it and transform them into links, inline.

Almost any text that a user inputted would be nicer if it did this automatically.

I don’t know about you, but I’ve accomplished this task in Angular in several ways like jQuery plugins or writing my own regular expressions. It’s not fun adding extra dependencies to accomplish this minor tasks. And it’s always a bit nontrivial to add link support without opening yourself up to some vulnerabilities.

I was quite surprised to hear that there’s a solution to this that comes builtin in Angular and since 1.0: the linky filter.

Setting it up

The linky filter does what you’d expect it to do. Let’s see an example.

First, as the docs say, you need to make sure that you include ngSanitize module file (angular-sanitize.js) and add it as a dependency to your module:

1
angular.module('myApp', ['ngSanitize']);

The basic usage goes like this:

1
<div ng-bind-html="blog.post | linky"></div>

This will take blog.post and display it regularly, except that URLs inside it, such as www.google.com would become links. Angular does this safely and sanitizes all the text.

You can quite easily make links open in a new tab or add specific attributes, such as rel=nofollow which is usually recommended when putting up links to user generated content:

1
2
3
<div ng-bind-html=
    "blog.post | linky:'_blank':{rel: 'nofollow'}">
</div>

And that’s it. Link away!

Always be in the loop for new updates to Angular and get guides for painless upgrading!

Configuring components with ui-router and ngRoute

| Comments

Angular 1.5’s upcoming .component() method is going to be very cool, as I wrote about previously. And in general the migration path to Angular 2 recommends that we all stop using controllers in favor of directives/components (for the rest of the post I’ll talk about components, but it should be obvious every component is a directive).

A lot of us are used to using controllers as the route-level objects. Each route has a controller that’s responsible for that specific route, and comes with its own template, etc.

This was comfortable since both ui-router and ngRoute allow us to easily set a controller that handles a route and inject it with dependencies using resolve.

Achieving the same with components isn’t as straightforward, but doable. Note: You might be thinking otherwise, but yes, components should be used for things that aren’t reusable, like handling a specific route.

ngRoute

Though I usually find ngRoute inferior to ui-router, in this case it’s nicer. Say that we’ve got this component:

1
2
3
4
5
myMod.component('inbox', {
  templateUrl: 'inbox.component.html',
  bindings: {mails: '='},
  controller: function() {...}
});

Passing it the mails dependency using resolve is pretty simple:

1
2
3
4
5
6
myMod.config(function($routeProvider) {
  $routeProvider.when('/inbox', {
    template: '<inbox mails="$resolve.mails"></inbox>',
    resolve: {mails: function(Mails) { return Mails.fetch(); }}
  });
});

Yes, ngRoute has a handy $resolve property exposed on the scope by default, which saves us some keystrokes and boilerplate in this case.

ui-router

The beloved ui-router doesn’t really support exposing resolved dependencies except to the controller of the state. The maintainers mentioned this might be addressed in the upcoming 1.0 version of ui-router.

Yes, it’s possible to hack things around in order to get access to this internal state. But that’s something I find dangerous and not very robust.

And so, our only pragmatic solution, for now, is to live with some boilerplate:

1
2
3
4
5
6
7
8
9
10
11
myMod.config(function($stateProvider) {
  $stateProvider.state('inbox', {
    url: '/inbox',
    template: '<inbox mails="mails"></inbox>',
    resolve: {mails: function(Mails) {return Mails.fetch(); }},

    controller: function($scope, mails) {
      $scope.mails = mails;
    }
  });
});

Yes. Not exactly the prettiest piece of code I’ve ever written. But, it gets the job done and allows us to rid ourselves of controllers and get onboard the component train. Choo-choo!

Always be in the loop for new updates to Angular and get guides for painless upgrading!

Angular’s .component - what is it good for?

| Comments

In my Angular 1.5 sneak peek I mentioned the new .component() method. A lot of people are quite excited about this method. But, as with anything new, there are open questions:

When should you use it?
Why should you use it?
What’s the difference between it and .directive()?

Today we’ll understand what exactly it does and whether it’s good for you.

Syntax sugar

First things first: this method is truly just syntax sugar for the good old .directive() method you know (and hate?).

There’s nothing you can do with .component() that you can’t do with .directive().

So what is it good for?

It aims to simplify the way we create “components” – which roughly means UI directives. It also pushes the community to use the defaults that have become best practices:

  • Components have isolated scopes by default
  • They automatically use controllerAs syntax
  • They use controllers instead of link functions
  • The bindToController option is on by default

If this sounds familiar, you might remember this is basically how I’ve recommended we write directive controllers in this post.

Show me the code: before and after

Here’s an example component directive:

1
2
3
4
5
6
7
8
9
10
11
app.directive('list', function() {
  return {
    scope: {
      items: '='
    },
    templateUrl: 'list.html',
    controller: function ListCtrl() {},
    controllerAs: 'list',
    bindToController: true
  }
});

It’s a simple component directive, with an isolated scope, binding, and a controller.

Here’s how you’ll write it with .component:

1
2
3
4
5
6
7
app.component('list', {
  bindings: {
    items: '='
  },
  templateUrl: 'list.html',
  controller: function ListCtrl() {}
});

As you can see, not much has changed.
But, things are simpler and more straightforward.
Also, we get to enjoy some default and save on boilerplate: bindToController is the default, controllerAs is on and defaults to the component’s name.
Another nice point is that we don’t need to write a stupid function that always returns the same object.
We just define that object right here.

When can/should you use it?

Clearly there are a few cases where you can’t/shouldn’t use it:

  • If you need the link function (though you rarely should)
  • If you want to use require to pass parent directive’s controllers
  • If you want a template-less directive, e.g. ng-click that doesn’t have a template or separate scope

For all your other directives, this should work. And because it saves on boilerplate and less error-prone it’s nicer to use.

I usually prefer to go with whatever would work everywhere.
And here it goes against .component() that it can’t fully replace .directive().

But, using it saves so much boilerplate.
And, non-component directives should be rare, which means they’ll stand out even more.

That’s why, in my opinion, using this new syntax is worthwhile. You can read the full docs about it here.

So, start using .component() once 1.5 is out: you have unlocked a new skill!

Always be in the loop for new updates to Angular and get guides for painless upgrading!

Angular 1.5 is close - here’s the interesting parts

| Comments

The first release candidate of Angular 1.5 was just released. This means the official release is probably right around the corner.

It can be hard to keep up with the changes in Angular. Things change pretty fast. I know a lot of companies that haven’t even moved to 1.4 yet (or 1.3, or 1.2). And everyone are trying to at least keep an ear open for the upcoming changes in 2.0.

And now there’s another version looming. When will you ever find the time to learn what’s changed?

Well, fear not fellow Angularist! I’ve gone over the changelog and gathered the interesting points below. In five minutes you’ll know what’s all the new rage about. Here are the interesting bits:

.component method

This is a new addition to Angular modules, along .controller, .directive, etc. The new .component() method is actually syntax sugar for creating a directive in the now-standard manner. This makes it easy to create isolated directives, with controllers using controller-as syntax.

This is a great step in the right direction of setting a proper Angular style in my opinion. But, it comes with a few interesting changes we’ll have to get used to. I will be writing more in depth about this soon (subscribe below to get notified!). In the mean time, there’s an excellent write up of all the options in Todd Motto’s blog.

Multiple transclusion

Finally. This means we can, at last, create reusable components with several transclusion slots.

For example, we can create a modal dialog directive with set sections, such as header and body, and use it like so:

1
2
3
4
<modal>
  <modal-title>My title</modal-title>
  <modal-body>The body goes here</modal-body>
</modal>

Prior we had to do all kinds of workarounds to get a similar solution.

While you may not be writing directives that use transclusion daily, it will make the libraries we all use much more powerful.

You can see the relevant commit here.

Lazily compiling transclude functions

This change means that things like ng-if (which you’re using instead of ng-show where appropriate, right?) will now work faster.

It might come as a surprise, but if you were using lots of ng-ifs that were never displayed on screen you still took a performance hit in page load time.

Luckily, 1.5 will improve this, making workarounds such as lazy-ng-if no longer necessary.

Not a lot of breaking changes

You should really go over the changelog, but from what I see it seems like most projects will be able to easily upgrade.

The breaking changes are quite obscure and shouldn’t matter for most of us.

Yay!

So, it seems like 1.5 is going to be a nice release. I’ll keep you posted if the next release candidates have any more interesting points.

Always be in the loop for new updates to Angular and get guides for painless upgrading!

Lazy Loading Your First Component in Angular

| Comments

A lot of web developers that come to Angular from other MVC frameworks are surprised to learn that there’s no official support for lazy loading.

Lazy loading is the common practice of not loading all of your source files on initial load. This can speed up your load times significantly in certain cases.

While some frameworks support this out of the box, with solutions like RequireJS, Angular doesn’t play that easy.

Angular 1.x has no support for lazy loading. In fact every solution is kind of a workaround for the way Angular expects to work.

Why doesn’t Angular support this? Well, to be frank I’ve seen relatively large applications get great load times by minifying all code to a single file. A lot of the times lazy loading is just premature optimization.

But say that you’ve measured, checked and finally decided you really need lazy loading.

Introducing ocLazyLoad

The ocLazyLoad library is a popular open source project for adding lazy loading capabilities to Angular.

I like it because it’s simple and doesn’t require a lot of fussing around to get your first component lazy-loaded. You don’t need to start extracting extra modules and make big changes to the way you structure your app.

It is really the simplest lazy loading solution I know for Angular.

Example: A lazy loaded ui-router state

Say that you have a ui-router state that’s seldom used and uses some big file you’d rather not load until needed.

Once you include the ocLazyLoad source (e.g. using bower) the job is pretty easy.

First, make sure you’re not loading the lazy loaded files on initialization. For example, you might need to remove the <script> tag from your index.html file.

Now, let’s configure our state appropriately:

1
2
3
4
5
6
7
8
9
$stateProvider.state('lazy', {
  url: '/lazy',
  template: '<lazy></lazy>',
  resolve: {
    lazyLoad: function($ocLazyLoad) {
      return $ocLazyLoad.load('lazy.directive.js');
    }
  }
});

This little snippet uses resolve to load the needed files before loading our state. I don’t usually use resolve, but this is a nice use case.

You can load multiple files here. For example, load your directive along some external and big JavaScript plugin.

And that’s it. We actually didn’t need to write our lazy directive differently than any other directive.

That was easy, wasn’t it?

Get more maintainable Angular tips and write Angular like it was meant to be written