codelord.net

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

Stop ng-repeating options: use ng-options

| Comments

A pet peeve of mine is seeing Angular code with <select> tags that uses ng-repeat to generate the options, like so:

1
2
3
4
5
<select ng-model="$ctrl.mode">
  <option ng-repeat="option in $ctrl.options"
    ng-value="option" ng-bind="option.name">
  </option>
</select>

One of the great little details about Angular is the awesome ng-options directive, which I find more concise and is very powerful.

First, here is the basic translation of the above:

1
2
3
<select ng-model="$ctrl.mode"
  ng-options="o.name for o in $ctrl.options">
</select>

The trick here is that ng-options is completely in charge of creating the actual <option> elements for us.

Now, let’s see where it shines.

Nullability of a select

When using ng-options, once you initialize the ng-model value to one of the options there’s no way for the user to reset it to an empty value by default.

To allow setting it to null, we simply add a special empty <option> tag. Here’s how the above example would look with nullability:

1
2
3
4
<select ng-model="$ctrl.mode"
  ng-options="o.name for o in $ctrl.options">
  <option value=""></option>
</select>

Using an object as a value

Another thing is that a lot of developers miss the fact that Angular lets us use selects with values that aren’t simple strings, but actual objects.

In the first example I showed how you do it manually, using ng-value, instead of the value property. This tells Angular to bind to our model the actual object that the expression evaluates to.

ng-options of course does that automatically for us, but we can customize the bound value even more if needed, for example:

1
2
3
4
<select ng-model="$ctrl.mode"
  ng-options="o.value as o.name for o in $ctrl.options">
  <option value=""></option>
</select>

Disabling elements

Another reason that I usually prefer using native HTML elements and not wrappers (e.g. Select2) is because they usually pack so much under the hood.

For example, you can easily have a few options be disabled dynamically:

1
2
3
4
5
<select ng-model="$ctrl.mode"
  ng-options="o.name disable when $ctrl.disabled(o)
              for o in $ctrl.options">
  <option value=""></option>
</select>

The disable when clause lets you specify an expression that decides which options will be displayed but won’t be enabled for actual selection.

So, please, don’t roll your own <option> elements unless you have a good reason!


Do you have an existing Angular 1.x app that makes you worried about its future?
You don’t want your app to be left behind and become legacy code.
But it’s not easy clearing the time to learn Angular 2.
And who has the energy to convince management that you need to change frameworks, delay your schedules and do the Big Ol’ Rewrite?

But what if you could make sure your app keeps its options open?
What if you could make it future-proof, all the while shipping features like a boss?
You’ll work in a codebase that uses the latest and greatest, have easy maintenance and happy stakeholders!

The Future-proof Angular Guide can help you get there.
With this no-fluff course you’ll learn how to quickly adapt your existing Angular 1.x app to the latest components paradigm, as you go about your regular work.
You’ll gradually turn your app into something that is modern and idiomatic, converting directives and getting rid of controllers.
And then, once your app is shaped The Right Way™, you’ll be able to keep shipping like a boss, and have your options open.

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!

Properly Wrapping Native JavaScript with $q Promises

| Comments

One of my most popular posts ever is the post about how a lot of Angular developers are using $q wrong (specifically $q.defer()).

Yes, in the vast majority of cases, you don’t really need to create a promise by your own from scratch.

But, in some cases it is a valid and powerful tool. The most common one is when you need to wrap some native JavaScript code that’s not promisified to make it play-along with your Angular awesomeness.

In this post we’ll quickly learn how it’s best to do it. There are 2 different ways of achieving this, let us go over them.

Our example would be a scenario where you’re writing some kind of image preloading service that should return a promise letting you know when the image has finished preloading.

Technique 1 – Using $q.defer()

This is the more barebones approach. The $q.defer() actually returns a “deferred” object.

This object has a .promise property, which returns your newly created promise.

It also has 2 methods, resolve and reject, which you can call at the right time to resolve or reject your promise:

1
2
3
4
5
6
7
8
function preloadImage(imgSrc) {
  var deferred = $q.defer();
  var img = angular.element('<img>');
  img.on('load', deferred.resolve);
  img.on('error', deferred.reject);
  img.attr('src', imgSrc);
  return deferred.promise;
}

As you can see, we first create the deferred object and then set up our preloaded image to point at it, and finally return the new promise;

Technique 2 – $q constructor

This is a very similar way to achieve the same thing, only more succinct:

1
2
3
4
5
6
7
8
function preloadImage(imgSrc) {
  return $q(function(resolve, reject) {
    var img = angular.element('<img>');
    img.on('load', resolve);
    img.on('error', reject);
    img.attr('src', imgSrc);
  });
}

As you can probably understand, $q’s constructor-function (or whatever this thing should be called) is syntax sugar for directly calling defer().

Personally I tend to use the second technique. Beginners usually understand it the first time they come upon it even without reading the documentation.

It also means a little less moving parts, which is always good.

And lastly, it’s just simpler – I have seen people waste several hours simply because they ended up doing return deferred instead of return deferred.promise, so why even risk it?


Do you have an existing Angular 1.x app that makes you worried about its future?
You don’t want your app to be left behind and become legacy code.
But it’s not easy clearing the time to learn Angular 2.
And who has the energy to convince management that you need to change frameworks, delay your schedules and do the Big Ol’ Rewrite?

But what if you could make sure your app keeps its options open?
What if you could make it future-proof, all the while shipping features like a boss?
You’ll work in a codebase that uses the latest and greatest, have easy maintenance and happy stakeholders!

The Future-proof Angular Guide can help you get there.
With this no-fluff course you’ll learn how to quickly adapt your existing Angular 1.x app to the latest components paradigm, as you go about your regular work.
You’ll gradually turn your app into something that is modern and idiomatic, converting directives and getting rid of controllers.
And then, once your app is shaped The Right Way™, you’ll be able to keep shipping like a boss, and have your options open.

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!

Not Everything in Angular Should Be a Singleton

| Comments

When all you have is a hammer, everything looks like a nail.

Angular services/factories are singletons. This has caused so many teams to forget about the joy of self contained objects that take care of themselves.

You don’t have to put all your code in static singletons and sling dummy json objects back and forth across your app.

You can enjoy real objects that make code easier to maintain!

How your code probably looks

You have a service for handling some kind of model, e.g. a Course would have a CoursesService. That service would be responsible for creating the courses and manipulating their data.

For example, you’ll use CoursesService.create(name, students, schedule). That will return some json object that you’ll then keep in your controller.

Whenever the controller would need some data about the course, it would have to use the service, passing it the object:

CoursesService.getEndDate(course)

Not only is this not very OOP-ish, it means that every binding you have in your template, e.g. to show the end date, would have $ctrl.getEndDate(course) which you’ll then implement in the controller just to proxy it to the CoursesService.

Also, having the course json object by itself isn’t usually enough, and to use it you’ll have to inject CoursesService.

Bleh.

How your code could look

Instead, we can create a real Course model that encapsulates its own data and knows how to manage by itself.

We create a service like so:

1
2
3
4
5
6
7
8
9
10
angular.module('app').factory('Course', function() {
  return Course;

  function Course(name, students, schedule) {
    this.name = name; // Etc.

    // Put the logic here!
    this.getEndDate = ...;
  }
});

And now, all of a sudden, our code has become nicer!

You create a course using new Course(...) and then just use this instance, instead of always holding on to an object and the service.

And, for example, your templates could now directly use $ctrl.course.getEndDate() instead of proxying it using the controller.

Huzzah!


Do you have an existing Angular 1.x app that makes you worried about its future?
You don’t want your app to be left behind and become legacy code.
But it’s not easy clearing the time to learn Angular 2.
And who has the energy to convince management that you need to change frameworks, delay your schedules and do the Big Ol’ Rewrite?

But what if you could make sure your app keeps its options open?
What if you could make it future-proof, all the while shipping features like a boss?
You’ll work in a codebase that uses the latest and greatest, have easy maintenance and happy stakeholders!

The Future-proof Angular Guide can help you get there.
With this no-fluff course you’ll learn how to quickly adapt your existing Angular 1.x app to the latest components paradigm, as you go about your regular work.
You’ll gradually turn your app into something that is modern and idiomatic, converting directives and getting rid of controllers.
And then, once your app is shaped The Right Way™, you’ll be able to keep shipping like a boss, and have your options open.

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!

$scope.$watch and controllerAs

| Comments

You know that by now your Angular code should be pretty $scope free. The controllerAs syntax makes it so you shouldn’t be accessing $scope in order to store information on it.

But, scopes are still an important part of Angular and sometimes you have to use them.

One not-so-rare example is the $scope.$watch() function. With the introduction of controllerAs syntax we now have 2 seemingly interchangeable ways to use it. But, they are not exactly the same and I think you should only be using one. Let’s quickly go over it.

The olden days

In the pre-controllerAs days we would put everything directly on the $scope.

So, you might have $scope.foo and then, to watch for changes, you’d use $scope.$watch('foo', fooChanged).

That just worked. But with controllerAs it’s not that simple. If in your controller code you use this.foo, you can no longer just watch for changes using $scope.$watch('foo', ...).

That’s because the 'foo' part looking for foo directly on the scope, not your controller’s instance.

The bad option – using the controller’s name

The way a lot of people are solving this is by using the controller’s name in the expression.

If you’re using Angular 1.5’s components then the controllerAs name is $ctrl by default. So you’d use $scope.$watch('$ctrl.foo', ...).

If you have a different name, like stuffCtrl then you’d use $scope.$watch('stuffCtrl.foo', ...) etc.

I don’t like this for several reasons:

  • It feels foreign to me to use a name that’s essentially only used in the template (the controllerAs name), while the rest of the controller code uses this or vm.
  • Using this name means that in case you decide to rename it, you’ll have to look for it in both the template and the controller code.

The right way

It was always possible to pass a function to $watch() as the expression that you’re keeping track of.

Because of that, it’s possible to do something like this:

$scope.$watch(function() { return vm.foo; }, ...)

(Of course, it’s even nicer if you’re using ES6’s arrow functions.)

I believe this is better, even though it involves more typing, because it keeps your controller code consistent. You always refer to things the same, and there are no magic strings.


Do you have an existing Angular 1.x app that makes you worried about its future?
You don’t want your app to be left behind and become legacy code.
But it’s not easy clearing the time to learn Angular 2.
And who has the energy to convince management that you need to change frameworks, delay your schedules and do the Big Ol’ Rewrite?

But what if you could make sure your app keeps its options open?
What if you could make it future-proof, all the while shipping features like a boss?
You’ll work in a codebase that uses the latest and greatest, have easy maintenance and happy stakeholders!

The Future-proof Angular Guide can help you get there.
With this no-fluff course you’ll learn how to quickly adapt your existing Angular 1.x app to the latest components paradigm, as you go about your regular work.
You’ll gradually turn your app into something that is modern and idiomatic, converting directives and getting rid of controllers.
And then, once your app is shaped The Right Way™, you’ll be able to keep shipping like a boss, and have your options open.

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!

Understanding Angular’s One-Way Binding

| Comments

Angular 1.5 introduced a new kind of binding option to directives/components. Along the often-used = for regular two-way binding and & for expression binding, we now have <: one-way binding.

What does it mean exactly?
When should you use it?
When shouldn’t you?
And why did we even need another kind of binding?
Sit tight!

How today’s two-way binding works

Today’s two-way binding basically has 3 aspects: passing the reference first, synchronizing changes from the parent and synchronizing changes from the child:

Passing the same reference means that when your child component is initialized with foo="$ctrl.foo" then Angular will pass it a reference to the same foo object as in the parent controller. This initializes them to start working off of the same data.

Because this is the same reference, changes made to a property on foo by either parent or child will be seen by the other, e.g. $ctrl.foo.baz = 'a'.

Synchronizing changes from the parent means that if our parent component overrides foo with a new object, i.e. this.foo = otherFoo then Angular’s watch will notice and change the child component’s foo to reference the same new object.

Synchronizing changes from the child are the other coin of the two way binding – if the child assigns a new reference it will also be copied to the parent.

You ain’t gonna need it

Even if you knew about the synchronization from the child to the parent, and most don’t know, it’s likely you never actually had to use it.

Having the objects be initialized with the same reference is enough for 95% of the components. The synchronization from the parent likely covers another 4.9%.

The other way around is just obscure, costs you in performance and, to be honest, sounds like a code smell.

Be explicit and don’t pay for what you don’t need

Basically, your rule-of-thumb should be to always default to one-way binding, like so:

1
2
3
4
5
6
7
angular.module('app').component('myComponent', {
  templateUrl: '...',
  bindings: {
    foo: '<' // <-- This!
  },
  controller: function() { ... }
});

It is always better to be explicit in code. One-way binding means you’re not doing anything funky to the object reference.

Also, there’s a performance penalty to using two-way bindings when you don’t need them. One-way bindings require less work on every digest and so you can also gain a small boost (I say small because from measuring it seems small – but it’s essentially free, why not?).

Cheers!


Do you have an existing Angular 1.x app that makes you worried about its future?
You don’t want your app to be left behind and become legacy code.
But it’s not easy clearing the time to learn Angular 2.
And who has the energy to convince management that you need to change frameworks, delay your schedules and do the Big Ol’ Rewrite?

But what if you could make sure your app keeps its options open?
What if you could make it future-proof, all the while shipping features like a boss?
You’ll work in a codebase that uses the latest and greatest, have easy maintenance and happy stakeholders!

The Future-proof Angular Guide can help you get there.
With this no-fluff course you’ll learn how to quickly adapt your existing Angular 1.x app to the latest components paradigm, as you go about your regular work.
You’ll gradually turn your app into something that is modern and idiomatic, converting directives and getting rid of controllers.
And then, once your app is shaped The Right Way™, you’ll be able to keep shipping like a boss, and have your options open.

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!

Understanding Angular’s & Binding

| Comments

Angular has several cases where the syntax trips you up, or where it’s just not clear what should you use. Most famously, there’s services vs. factories and ng-show vs ng-if. More recently we now have components vs. directives.

Another thing that I’ve seen people get mad about time after time is the & binding for passing functions to directives/components. “The & callback binding trips me up EVERY TIME I just it.”

Let’s understand exactly what it is. Once you grok it, you’ll never get it wrong again.

Can you use it in a sentence?

First, here’s an example component that has one of these & bindings:

1
2
3
4
5
6
7
8
9
10
angular.module('app').component('foo', {
  templateUrl: '...',
  bindings: {
    callback: '&'
  },
  controller: function() {
    // ...
    this.callback();
  }
});

As you can see, we have a simple binding called callback. The usage of this component would look something like this:

<foo callback="$ctrl.myCallback()"></foo>

This means that whenever the foo directive would call the callback binding, the myCallback function on the caller’s controller would be triggered.

The tricky bit: parameters

Now, what everyone get mixed up with is using & with functions that get parameters.

Say that our callback wants to pass an argument. The component would be created like so:

<foo callback="$ctrl.myCallback(value)"</foo>

But inside the component, we calling syntax would look quite foreign the first time you see it:

this.callback({value: 'whatever'});

WAT

Yes. Doing something like this.callback('whatever') wouldn’t work.

What’s going on?

Technically speaking, when you use the & binding, Angular doesn’t just do 2-way binding the regular way.

It takes the expression you use, in our example $ctrl.myCallback(value) and saves it.

When you call it, Angular evaluates that expression on the parent scope.

You see, when using & you don’t have to pass function, though that’s what we do 99.9% of the time. You can pass in any expression, and it would work.

So, in our example, we could have used:

<foo callback="$ctrl.values.push(value)"></foo>

And whenever we’d perform this.callback({value: 'whatever'}) it would get appended to the parent controller’s values array.

Because the & binding is so generic, it doesn’t really have a notion of function parameters – the expression could be anything.

When you pass it the object, it is actually a mapping of local variables to override. Angular takes the expression and evaluates it in the parent scope, but with the values you pass it added as the locals.

Wiseass note: Yes, this means we can call this.callback({value: 'whatever', $ctrl: something}) and the function call would be performed on the something object and not on our parent controller – because we override it!

Dear god, why?!

This was done so that you’ll be able to pass expressions instead of functions to anything in Angular.

Have you ever used ng-click="$ctrl.value = true" or something along those lines? Sometimes it’s easier to not use a function.

The core team wanted us to have this flexibility, and the price is that we have to call function in a way that feels a bit clunky.

But remember: You’re not really calling a function, you’re evaluating the expression with those values!

Now you know

If you’ll make the mental switch from treating & as “function binding” to just “expression binding”, I think you’ll be alright from now on.

Don’t get tripped up - subscribe to get more posts and really understand Angular!

Using ES6 Arrow Functions in Angular 1.x + Cheatsheet

| Comments

ES6 is becoming more and more popular among the JS crowd. I’m guessing that the first feature anyone that moves to ES6 starts using is arrow functions. And the recently released Angular 1.5 introduced support for injecting dependencies into arrow functions. Unfortunately this support added a couple of nice pitfalls for newcomers that are important to understand and avoid.

Quick background on arrow functions

In case you’re not familiar with these, they basically look like this:

1
2
3
(arg1, arg2) => {
  return arg1 + arg2;
}

Which, unsurprisingly, maps to:

1
2
3
function(arg1, arg2) {
  return arg1 + arg2;
}

Note: There’s a lot more syntax sugar that makes these awesome, like array.map(x => x.name). They can really save up on some typing and make code cleraer. Get the cheat sheet at the bottom of this post for the full list!

An important feature of arrow functions is that they bind the this value.

Most JS developers are well versed in the practice of keeping a reference to your “real” this value, e.g. var self = this or var vm = this. This is because every function you then declare inside the object might have a different this value assigned to it at runtime, which makes for very fun bugs.

Arrow functions do this for you behind the scenes, so that inside an arrow function you can freely use this and it’ll be the same this as in its parent scope.

The pitfalls

I like arrow functions very much. First, because they mean I need to type less, which is always a good thing. But mainly because using arrow functions means I don’t need to declare a self var anymore or think about what this means as often.

The main problem is when people assume they can just start using arrow functions everywhere, and say goodbye to the regular syntax. But that’s not the case.

Arrow functions should never be used for constructor functions.

They are always anonymous and have no prototype, which means they are not newable. And of course using them as constructors is wrong since a constructor should not be using its parent scope’s this value.

The Angular-Arrow function rule of thumb

The most common constructor functions in Angular are controllers and services.

So, to be safe, never use arrow functions in module.service('Service', ...) calls and not when passing a controller function as controller: ... when defining components/directives/etc. (and also not in module.controller() calls, but you should hopefully not have any more of these).

Personally, I don’t like it when all my files don’t look the same, and I prefer my style guide to reduce thinking.

Because of that I simply recommend to not use arrow functions as the function parameter to any module.something() call (where something can be service, factory, directive, run, etc.) and never when passing a controller function.

Happy arrowing!

Get the cheatsheet and learn how to use arrow functions to write less code!

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!