README: Angular 2 has changed significantly since this post was written. As such, please do not use this code verbatim. Instead, focus on the concepts below and then map them to the new syntax and API of Angular 2.0.0.

Welcome to the second post in our series on Angular 2. If you missed the first post, check out the quick Intro to Angular 2.

In this post, we are going to talk about Components, which elegantly replace the mix of controllers, scopes, and directives from Angular 1.

The death of scope

If you missed Igor and Tobias’ great talk at ngEurope in October, they quite dramatically proclaimed the death of a variety of Angular 1 concepts, including controllers and $scope. I was there, I and remember the gasps and nervous laughter from the crowd as a series of ominous gravestones flashed on the screen:

RIP Angular 1

The uproar from the broader community was immediate, with scathing comments, high-profile departures, and plenty of overly-dramatic banter to make it really exciting.

Though it made for good TV, the reaction was unwarranted. Those new to Angular 2 quickly see how the new component model is a lot easier to use than what we had in v1.

The “Component”

Angular 1 wasn’t built around the concept of components. Instead, we’d attach controllers to various parts of the page with our custom logic. Scopes would be attached or flow through, based on how our custom directives encapsulated themselves (isolate scope, anyone?).

I don’t really know how to describe the model in v1, but it wasn’t like any other hierarchical system I’ve ever used. We’d just “attach” behaviors to various parts of our page and then have to deal with the complicated meta-structure created by our directives, controllers, and scopes.

To add logic to the page, we’d have to decide between building a controller or a custom directive.

In version 2, Angular drops all of this for a much cleaner, more object-oriented Component model.

Our first component

If you’ve ever written Java, C#, or any other language with strong OO patterns, you’ll immediately understand a component. It’s just a class that represents an element on the screen, with member-data that influences the way it looks and behaves.

Just like a JComponent subclass in Java (Swing), or a Control subclass in Windows Forms development.

Let’s see an example:


import {Component} from '@angular/core'

@Component({
  selector: 'my-component',
  template: '<div>Hello my name is {{name}}</div>'
})

export class MyComponent {
  constructor() {
    this.name = 'Max'
  }
  sayMyName() {
    console.log('My name is', this.name)
  }
}

This creates a new component called MyComponent, which will be identified in markup as <my-component>, just like restrict: 'E' did in v1.

We can specify a template for the component with the template property in @Component annotation (annotations are an es6 extension added by both AtScript and TypeScript, though only TypeScript will be relevant going forward).

Member data

If we look closer at the example above, we don’t see $scope anywhere. Instead, we see this.name = 'Max', and a member function (“method”) called sayMyName(). If you’re familiar with Controller As syntax in v1, the use of this will look familiar to you.

Even so, this is different. When our component is “instantiated” and rendered on the page, we have an instance of our component. We can modify the instance data of that component, call methods on it, and pass it around to other components. It’s just an object!

More tangibly, imagine we have a Button component. The component has a this.title for the text of the button, and a click handler. Previously, we’d either build a new directive for the button, maybe add an isolate scope with some events and two-way data bindings, or get lazy and just attach a controller to it (or one of its parents). With Angular 2 components, we get a natural combination of all of these concepts: our Component has encapsulated instance data (much like isolate scopes), event handlers (much like methods attached to scopes), and a template (much like directives).

We can even inherit from other components or attach components through attributes, and access parents and siblings (more on that in a future post). This is a far easier, less error-prone way to replace require from directives in v1.

ngApp?

In the previous post, we briefly mentioned the bootstrap process, the process by which an Angular 2 app powers itself up. In v1, we had ng-app, or we could manually bootstrap. In v2, there isn’t an ng-app. Instead, we provide our own root Component from which we want to start the app:

<app></app>

which would look like this as a v2 component:


@Component({ 
  selector: 'app',
  templateUrl: 'main.html'
 })

class MyApp {
  constructor() {
    console.log('App Start')
  }
}

bootstrap(MyApp)

What we’d often see in Angular 1 was ng-app and ng-controller used on the same element, like this:

<body ng-app="myspace" ng-controller="AppCtrl">

Then, our AppCtrl would create some root scope data that our child controllers would access and/or extend.

In v2, we get all of that in one Component.

I really like this change. If you think about your document layout, it’s really just a tree. The root shouldn’t be any different than every other element, even though it was in v1.

With the change to the component model, we need to change our mindset a bit. Instead of attaching our custom logic to the page with controllers, we put that logic into components. If we want a certain part of the page needs business logic, we create a new component for it. If we are using an existing component but want to attach behavior to it, we can extend it.

Annotations

Let’s dig in a bit to the @Component annotation above. If you recall, these are extensions on ES6, which are becoming part of TypeScript which Angular 2 will use.

Basically, these annotations allow us to attach information to our component. We can configure the selector our Component will look for to instantiate itself (like <my-component>), and also set the template.

@Component is the core annotation, and has a few important parameters:

@Component({
  selector: 'my-component',
  providers: [MyService],
  // Url based template
  templateUrl: 'main.html',

  // Inline template
  template: `
    <div>
      <button></button>
      <ng-content></ng-content>
    </div>
  `,
  directives: [Button],
})

The selector param is the replacement for the auto-naming system of directives in v1 and is now explicit: you must set it to exactly what you want the new component to be named in markup. It works much like querySelector.

The providers param is part of the new Dependency Injection system, and configures which services we want to inject into our component (more on this in a later post).

We can use provide a template either inline, using template, or point to an external file using templateUrl. This similar to how we defined templates for custom directives in Angular 1. Notice the use of the awesome new backtick Template strings in ES6 that let us easily create multi-line templates!

We also reference the child directives we want to enable so they are compiled and instantiated (I hope this changes in the future so you don’t have to explicitly specify child directives).

Finally, we should note the <ng-content></ng-content> tag in our template. This is the new “ngTransclude” and specifies where child content will be injected. You can have multiple ones and target different spots to include child content (more on this in the future!)

Conclusion

A lot is changing in Angular 2, and few things as dramatically as the way we build and specify components on the page.

Though it’s scary to move on from our beloved scopes, controllers, and directives (concepts that we worked so hard to learn and learn to love), it’s really a wonderful thing. With the new component model, Angular is moving into much more familiar OO territory, and is setting itself up to work with the future of web standards, like Web Components and Shadow DOM.

Once you get used to the new model, it’s hard to go back. I think the community will learn to embrace the changes and appreciate how they make Angular 2 so much better.

In our next post, we will talk about “New-way” data binding: the untimely death of 2-way data binding! Stay tuned.

54 Comments

  • Avatar Fernando says:

    Awesome intro tutorial. The new angular kinda reminds me a little bit about react, which is good.

  • Avatar LivelyWorks says:

    This series is awesome!!
    Helping us to move towards Angular 2 Smoothly.

    Thank you

  • Avatar Arnold Krumins says:

    Really starting to like Angular 2. I can definitely see advantages.

  • Avatar Palle Simonsen says:

    Ionic have demonstrated the very best that can come out of (F)OSS development – an awesome framework, best-in-class, driven by talent, energy and seemingly good teamwork. The numbers speak for themselves as do the quality of many of the apps produced with Ionic.

    Angular2, however, demonstrates one of the biggest problems with (F)OSS development, namely the lack of accountability towards an installed base – one of the nicer comments I read were: “Wow. I do not envy the person who has to tell the boss that the entire project has to be scrapped by the end of 2015 or face going unsupported for the next 15+ years.”. On top of that Typescript is a language with mixed receptions.

    What I would like to know is what the Ionic team is thinking in terms of migration. Is it ‘scrap the old stuff and reprogram’ or are there any realistic means of reusing any factory, service, controller or template code? And if not; for how long will Ionic 1.x be supported and how?

    • Avatar mhevery says:

      In ng-conf, we have made a commitment to support v1 while significant people are still using it. So if you have an app in v1, you can stay using v1 and you will be supported, no need to upgrade.

    • Avatar Adam Bradley says:

      Ionic 1.x will continue to be supported after Ionic2 comes out, same as Angular 1.x. Since Ionic2 is not completed yet we haven’t finalized a migration path, but there will be one for those who choose to upgrade.

      • Avatar Palle Simonsen says:

        Hi Adam,
        This is what I want to hear. It is understood that it is early days. I take it that you will convey more information on the roadmap when ready.

        Brgds, Palle

  • Avatar mhevery says:

    Thanks for the write up, I could not have said it better myself.

  • So IONIC v1 will keep using angular v1 or will be soon migrated to v2? just to understand if i’ve to go back to jquery mobile or not 😛 or search another way of doing those apps.

    • Avatar Denis Andrejew says:

      Ionic v1 will stay on Angular v1, Ionic v2 will be using Angular v2. Breaking the API means incrementing the major version number (1->2), so that’s what’ll be happening here.
      (Edit: It would be just really silly to give up and break Ionic v1 while it’s a perfectly working and valid version of Ionic in and of itself.)

  • Avatar szahn says:

    How would “scope” inheritance work in Angular 2? Would components then inherit from other components? Wouldn’t all this deep nesting of inheritance be an anti-pattern?

    • So far as I know there is no scope inheritance. Which is probably a good thing as it makes it very difficult to reason about your code. I’ve stopped using scope inheritance completely in my 1.x apps.

      It’s convenient but can blow up in your face as complexity goes up.

  • Avatar Mithun says:

    Is there any forked project of Ionic for Windows Phone support? I desperately need one! 🙁 What I understand from the official Ionic team is that they have no plans to start supporting WP “now”. They just have it in their least-priority TODO list. So I really appreciate anyone to introduce me to frameworks that support WP (I want only Ionic fork. Not others unless they are as good as Ionic).

  • I was wondering if you were using the new router in ionic 2, or just waiting for a final release?
    Otherwise how do you manage the routes/states of your app?

    • Avatar yesimahuman says:

      Hey. That depends on a few factors. We need a router w/ non linearity like you see with a tree of UINavigationControllers (to use the native iOS example). We have been involved with the new router discussion, so I’m really optimistic, just need to wait a bit on it.

      That being said, we aren’t sure we want to do routing like we did in v1. It is pretty complicated, and we allow for pretty powerful deep linking that I’m not sure is worth the complexity (rarely do native apps deep link more than one history state deep, for UX reasons).

      I’d personally like seeing URLs take less of a role in v2 for hardcore internal routing, instead favoring states and local routing (push/pop inside the closest navigation stack).

      Stay tuned!

  • Avatar Calebe Aires says:

    AngularJS 2 has some point of ReactJS… Will Angular2 + Ionic go on the React Native way?

  • Avatar nielskrijger says:

    Looks a lot like Java’s JSF; which is not a good thing.

    How vague and abstract is the term “component”? Everything in the world is a component… Will it have complex component lifecycles also like JSF? These components need to be managed by something; which needs to be altered/extended on…

    Annotations I would regard as an anti-pattern really. The original branding/popularity of POJO’s was to simplify stuff; now check any Java codebase and those simple plain old java objects have become a wishwash of hundreds of annotations (I’m not joking, I wrote plenty myself).

    I’m particularly afraid this will be fun for some time learning a bit of new stuff, but looking back at your code two years later and I highly doubt it will feel clean or simple (not that angular 1 is clean or simple). Particularly with ES6 and ES7 in the future rendering typescript a bit unnecessary frankly.

  • Avatar Badru says:

    Thanks for sharing

  • Avatar Ryan King says:

    Are annotations required? This seems like a silly question, but it has been mentioned many times bye the Angular team that Angular 2 can be written with regular ES6. Any examples I have seen require developing in TypeScript simply because of the annotations.

    • Avatar evanplaice says:

      You can use ES6 with annotations in both Babel and Traceur. Babel requires an additional plugin + configuration. Traceur requires configuration.

      If you use JSPM + Traceur, add the following to config.js:

      traceurOptions: {
      “annotations”: true
      }

      Typescript is definitely not required, there’s just little/no documentation available for using Angular2 + ES6.

      If you’re curious and want to see NG2 + ES6 in action check out my site:
      https://github.com/evanplaice/evanplaice.com

  • Avatar Naveen Singh says:

    nice descriptive post, but i would like to know does angular-v2 keep support the two-way data-binding or it would move two one-way data binding.

  • Avatar Valiant200 says:

    I am a bit worried that we are not seeing any es6 based tutorials.

  • Avatar rvanhoepen says:

    To be honest at first I was really against some of the changes coming in Angular 2, but these posts are really helping me see why these changes are going to be great and you are making me excited to start implementing them in my projects. Thanks for the time and effort you put into explaining the new concepts Max!

  • Coming from an OO software background using Java and C#, this is great news 🙂
    Much more comfortable territory.

  • Avatar David Cornelson says:

    I’m still waiting for information on services. Did I miss that?

  • Avatar pacomerh says:

    This is good. Basically I needed a reason or a problem to solve to get into Angular, and mobile apps is a very good one.

  • Avatar Wisam Fadel says:

    Thanks you, I can’t wait for Angular 2

  • Avatar Alex Ford says:

    So, to use Angular 2 do we HAVE to use the Typescript transpiler? I hate working with transpilers. Is there no way to use Angular 2 as plain JS?

    • Avatar evanplaice says:

      You don’t HAVE to use Typescript. You can use ES6 with Babel/Traceur + decorators enabled.

      You can also write pure ES5 but I don’t recommend it. Decorators are basically high-order wrapper functions that add a lot of additional functionality. Trying to replicate the same functionality in pure ES5 requires a lot of extra work.

    • Avatar Vance Feld says:

      typescript isn’t really a transpiler… it just removes itself 🙂 (if you’re targeting es6)

  • Avatar ismavolk says:

    Thanks!

  • Avatar murali krishna N says:

    Hi Max,

    Thanks for your wonderful articles. I have a small doubt in Angular 2.0 as I started reading since yesterday.

    When everybody writing a component they were writing the class just below the Annotation section as below. Since we will write so many components in our projects lets say if I write two components in a single file in that case how the component decides which class it has to use.

    //Anotation section
    @Component({ selector: ‘app’ })
    @View({
    url: ‘main.html’,
    })
    //Component controller
    class MyApp {
    constructor() {
    console.log(‘App Start’)
    }
    }

    • Avatar evanplaice says:

      The decorator applies to the class directly following. The same way as it works in Python.

      As long as you do decorator first immediately followed by the class there won’t be any issues with putting multiple components in the same file.

  • Avatar Mikko Kämäräinen says:

    Web Components
    for those who want to try out components the easy way / online, no installations: I made a Codepen collection with starters for a few alternatives. Angular 2.0 and Aurelia are iframes to Plunker, as they require several .js ad .html files. Available starters currently for: Angular 2.0 preview, Angular 1.4 RC2 with ES6 via Babel (possible to create components 2.0 style), Polymer and of course Aurelia.

    Feel free to fork from: http://codepen.io/collection/XPYmZa/

  • great info, thanks!

  • Avatar Binh Thanh Nguyen says:

    Nice post

  • Avatar Torgeir says:

    I have been playing around with the incremental alpha releases and so far so good. Have added my poc work here in case you want to see some current examples: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples

  • Avatar Kerensky87 says:

    These Angular 2 posts are a great resource for understanding the changes from v1. Please continue this series of blog posts!

  • Avatar Ajay Singh says:

    Just finished learning ionic/angular and was about to start building app with ionic1/angular1 and all of a sudden things chnged.but coming from OO background its looking better. Plus your blog is making it really easy to learn the new angular.
    Thanks

  • Avatar Mapleiny says:

    I’m doing something with Angular 2, and I’m wondering if I can change the directives array base on what i want. the the screen shoot may be show what I mean. thank you!!

  • Avatar Vance Feld says:

    does @View still apply? seems like you just specify the template right in the controller now? for RC1

  • Avatar Peter says:

    I am having difficulty figuring out how to communicate between components – for instance how to add/remove classes in sibling components:
    1) A list of cards with checkboxes
    2) On selection of two checkboxes
    3) Add a class on a (compare) button on a header component
    Thank for any help!

  • Avatar Jolly Geoff says:

    ng-content is like ion-content or different

313 Trackbacks