Curious about the new Angular 2 template syntax features? In this preview, John will take you on a tour.
...disclaimer, Angular 2 is a work in progress and many things can and will change.
Angular 1's "Hello World" example looked exactly like this, where you created an ngModel and it had a your name property. You bound to your name, so it set up this your name property on the scope, and then set up a watcher. If your name ever changed by this input changing, then this would also update.
Angular 2, on the other hand, treats this quite a bit differently, because instead of ngModel, you now work with the elements and their values themselves. If you want a value off this input, I say, hey, I want a reference to this input, I'll just use the pound sign and "ref," you could name that anything. Then you bind to ref.value, meaning, look at this input and grab the value, because this ref is pointing to that input.
Now, if I refresh here and I start typing, nothing will happen because it hasn't set up any watchers. That whole concept of watchers has changed quite drastically as well, using a new concept called zones, which looks for addEventListener to be added somewhere on your project.
To add that, I'm going to say I want an event listener on keyup here and we'll get more into this syntax in a second, but when I refresh now, and I start typing "J-O-H-N," you can see it works just fine.
An important side note is that because of the way that it looks up a reference, if that reference is not defined and it can't find ref.value, when you try and run this, you'll now get an error telling you that it cannot find this.
It's not going to try and create some sort of model with the property for you, it's just going to say, "Sorry, I don't have that reference," and you'll get that error in the console. In the future, the various tools that you'll use to write Angular will let you know that this is an error before you even get to the browser.
I'm going to put this ref back and delete the keyup, which means that it's no longer going to update every time I type. Now I'm going to add a button here and give it an ID of "button," because I'm going to want to look this up and say, "Click me."
Now, I'm just going to add a quick addEventListener 6to this button, so I'm going to do it in the constructor. You could do it anywhere in your code. Just documents, query, selector. Then don't worry about this selector, it's just a way of reaching into a shadow DOM just for the purposes of this example.
I'm going to say addEventListener, click and then handle the click and just say, "Click."
Now, the way you handle events through Angular is by typing the name of the event and surrounding it with parens, so I'll type "click," and then I surrounded it with the parens there. Then you set it to something that you put on your controller, so on click needs to be on your controller as on click.
Then we'll just log out, Angular clicked. We'll refresh, hit "Click me," and you can see that Angular's now grabbing that click and logging out what's going on.
Now, further proof that this reference is a ref and it's nothing on the scope, it's just referring to this input and actually getting that element, you can pass that into the event, say, value here and log out the value. You can see when we refresh now, and I click, you can see we get an input back. You are actually working with elements from the DOM in Angular now.
The awesome thing about this syntax, where you wrap an event name with parens is that you can now listen for custom events dispatched by your elements. If I grab this query selector, I call it button, and then I'll just say, set interval, pass in a callback, that's invoked every one second.
Then just have that button dispatch an event, which will just be a new event, called "Custom," we can listen to that event with our parens custom and just setting up a handler like on custom. Come down here, say, on custom, and log out custom. I'll refresh and you can see that we're now handling that custom event.
Custom events is something that Angular 1 couldn't do because it included all the different ng-click ng-whatever event name directives with it. For any custom events, you needed to set up certain behaviors to handle them. But now with this syntax and the semantics behind it, this enables you to use any sort of web component or anything that dispatches a custom event and just handle it through Angular using the parens.
The last thing to talk about is how to change a property on an element, so we will use these square bracket syntax here and say, style.color, because every element has a style object on it with a color property.
That means we combined it to our ref.value and I'll add our keyup handler again, so that when I refresh and I type "red," it changes red. When I type "blue," it changes to blue, "green," to green, and that just demonstrates how you can look up any object on an element and set any property on it and then just pass in the value that you want to set whenever change detection is fired.
A huge takeaway from this is that you'll never write curly b races inside of your attribute values here. It's always going to be new syntax on the left hand side.
This is very powerful, because it enables things like custom events or custom properties on your elements, ways of looking up what those might be and then setting the different values to them. Whether that value comes from a reference inside of your HTML itself or whether it comes off of your controller, it doesn't really matter.
Another huge flexibility win is because of this being more of a strict look up to find a reference or something off the controller, you will get proper errors through the dev tools and through your own IDE tools or other tools you build. To catch any errors before you run it in the browser.
Lastly, the new change detection system in Angular 2 is going to let you update on any sort of event that you'd want to. You don't have to call scope apply anymore, which allows you to easily use Angular 2 with any other libraries or anything from other projects that you've already written.
We'll start by deleting this entire constructor and get rid of all that selector stuff, and we'll create a clock component, which I'm going to do by copying all this stuff, pasting it here, calling this component "Clock," removing this entire inline template, and just creating a div that says clock. Then we'll create our controller to handle the clock.
To dispatch events from this clock, we'll set up a constructor, and we're going to inject something called an event emitter, which I'll need to import here. That event emitter can easily define a type, we'll call it "tick," and then a function 6that can be invoked to dispatch that event type.
If I do a set interval and use a fat arrow function to call tick every one second, then it'll dispatch a tick event every second. To make it way more interesting, let's do a time zero and then send the time along as the event object. Just incrementing by one each tick.
To use this clock in our template, we need to say directives, which is an array and we just say "clock," and then anywhere that a clock selector is used, so clock, it'll go ahead and create all of this clock component for us.
Now, remember, the whole purpose of this was to listen to a custom event, tick, which is being dispatched, which we can go back and use tick and in our component, say on tick, take the event as well. Then instead of on custom, we have on tick, which has the time, and we can just log out the time. I'll save, hit refresh, and you can see we now have the time being logged out in the console.
Lastly, let's remove this keyup thing that I set up right here and instead change it into a decorator on our input. If I create a new decorator, which looks like this guy, I give it a selector of input and we'll tell all of our inputs, look for certain events, such as keyup, and if you find him, trigger on keyup;. Make sure to invoke him and it's a class input decorator to handle on keyup.
This is really going to do nothing because we're just using this so that on keyup, it knows to trigger the change detection.
To finish this, we just need to make sure to import the decorator and also to use our input decorator in our list of directives. Then when I refresh, and I start typing red, you can see it changes as I type the keys.
This shows an example of using a component with a custom event and handling that custom event on our component and also changing the behavior of an input and what happens on keyup by using a decorator.