Constructing A User Interface With Angular

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 83

Course Overview

Hi! My name is David Mann, and welcome to my course, Constructing a User Interface


with Angular. I'm the cofounder of a software startup, and between that and my
day job as a contract developer, I've created several large Angular applications. One of
the things I've learned about building those applications is that Angular's an even more
impressive framework than it appears on the surface.There's so much to it. So many
little nooks and crannies that take a while to learn, but once you do, it's like the world
is your oyster. You can deliver better applications more quickly and with less
code. We're focused almost exclusively on elements that impact the user interface in
this course, but not how to design that interface, rather, how to write the code to
deliver it. We look at lots of code, but I'm as interested in teaching you the concepts
and what's possible as I am in teaching you syntax. Some of the major topics that we'll
cover include querying the UI, how to connect to the DOM elements we need to
manipulate. Once we have access to those items, we'll see how we can
manipulate them easily and without destroying the loose coupling we want
to maintain as a good practice, dynamically creating components and forms based on
runtime requirements, and doing all of this while maintaining good performance. We'll
also look at why Angular and jQuery are mutually exclusive, meaning if you've decided
that Angular is the right framework for a project, you've also decided that jQuery is
not.Coming into the course, I expect that you're at least somewhat familiar with
Angular 2 or better. You don't need to have a lot of experience as you'll be exposed to
everything as we go, but a basicexposure to the constructs of the framework will be
helpful. By the time we're done, you'll have a solid understanding of all of the Angular
elements involved in the UI layer and how to make your UI pop. Are you ready to jump
in and see what the Angular UI is all about? Let's go! It's time to learn everything you
need to know about constructing a user interface with Angular from Pluralsight.

Getting Started

Getting Started

Hi and welcome. In this course, we're going to look at all kinds of things that can help
you build better, more responsive, more performant, more user-friendly applications
with Angular. Although we cover some introductory level material in the beginning
of the course, this isn't a beginner course. Once we get past a quick level set, I assume
that you're all familiar with Angular and so don't cover a lot of basics, although we do
look at some basic stuff with what I think are some unique and interesting twists. My
name is David Mann, and I'm a full-stack web developer, which I think is just code for I
used to do server-side development, but I switched to JavaScript a couple of years
ago. In my case, that switch was over 10 years ago, but I've kept up my server-side
chops too. In addition to consulting work, I'm CTO and cofounder of a little software
startup keen on taking over the genealogy world. My goal in this course is perhaps a
little different from other courses you may have come across. I'm as interested in you
leaving this course with questions as with answers. By that I mean I want the material
presented here to make you think. I want you to learn concepts, as well as syntax, and
walk away from the course thinking about where else you can use the material you
learned here. I want to both teach you a few new things, as well as spark
your imagination to come up with your own uses for the material we coverand other
aspects of Angular 2. A few final comments before we get started. First, I'm a lousy
typist. There, I admitted it. Isn't that the first step to solving a problem? Seriously,
though, you're not here to watch me hunt and peck at the keyboard, so all of the
demos I'll be showing are fully typed out. That way we can focus on the code instead of
me painfully trying to type everything properly. Second and more importantly, while
I'm interested in you learning syntax, and we spend a good amount of time looking at
code, syntax is not the most important thing I can teach you. You can Google syntax
until you get it memorized. If I can teach you concepts and what's possible, as well as
perhaps a different take on some things or how to start looking at things differently,
then that's far more valuable than where the semicolons go. We do cover a lot of code,
but I kind of assume that you're already familiar with JavaScript and some Angular. So I
don't need to painstakingly go through each example line by line. If you need to, pause
the video to study something further. Here's what we're going to cover in this
course. You can read it as well as I can, so I'm not going to read each topic to you. I'll
just say that the first piece, Building Blocks, is our level set module. I cover some basics
in there, but also provide what I think are some unique takes on those basics. Even if
you're comfortable with things like components, directives, and pipes, I'd recommend
watching that one. It's only 20 minutes, and it has a few interesting bits that you
may not have been aware of. I'll also mention that very last item there, Use Cases. As
we go through the course, the demos and the material that I'm talking about are very
specifically focused on teaching the concepts. So in the last module, I spend some time
thinking and talking about use cases, about where you can take the things that we've
learned and put them to use.One final thing, if you're not aware of it, you can jack up
the play speed of the videos to consume more content in less time. In Pluralsight's web
client, look for the gauge icon at the bottom of the player and click on it. You can safely
crank me up to 1.2X or 1.3X without making me incomprehensible, so you can get
through the content a bit faster without losing anything. If you need to take your time
with something, just drop me back down to normal speed. The various mobile players
all have a similar capability. Enough stalling. Let's get started.

Understanding the Available Building Blocks


Introduction

The first thing we're going to talk about is the building blocks available in Angular to
build a user interface. For the most part, I'm going to assume that you're already at
least familiar with these elements, so we're not going to cover them at an introductory
level. Instead, we'll see them in use in our demos and spend the bulk of our time
covering more interesting things. Here's a quick look at what we are going to cover in
this part of the course. As I said, a quick overview of the building blocks, so we'll
spend some time talking about components, some interesting things about directives
and directive selectors, and then finish this part with a quick review of pipes. Let's go
ahead and get started. Every Angular UI is built from the same three constructs--
components, directives, and pipes. Forgoing for now the fact that components
are really special case directives, we're going to start here.Components and specifically
their templates specify the bulk of what's displayed on the screen. Components also
specify the CSS and JavaScript used to style and bring interactivity to that
content.Directives can alter what and how components or HTML elements display
content. And pipes can alter the presentation of specific pieces of data. There's more
to each of these, some of which we'll be looking at throughout the course, but some of
it we're going to skip over if it doesn't impact the UI of our application. Again, I'm
assuming you have some familiarity with each of these, so none of this should look
new. We are going to cover a little bit of foundational Angular stuff in this course, but
most of what we're going to cover assumes that you're familiar with at least the three
elements we saw on the last slide. If components, directives, and pipes are totally
foreign to you, I suggest you spend a little time with one of these three courses before
coming back here to really dig deep into the UI. These three are a starting point, and
we pretty quickly dive deeper from there. Each of the courses here provides a good
foundation on Angular basics and more than just the UI and will give you a background
to build upon with what we're going to cover in this course.

Components

We're going to start with components. Good components are three things. Modular,
meaning that they can be added to or removed from your application with ease to
meet requirements. Atomic, that is, they deliver as small a unit of functionality or
of the UI as makes sense. Components should generally focus on one thing and one
thing only. Self-contained--adding or removing components or changing component
parameters shouldn't easily impact other components on the page. Of course,
sometimes you need to have some interaction between components, and we're going
to cover that shortly. But the important thing is that those interactions are
deliberate and happen in specifically designed ways.There are a number of ways to
think about components and where to draw the boundaries between them. It could be
from a development and maintenance side--what elements are likely to be part of
arequirements change together? That might be a good place to break things out so
that they can be worked on by a single developer or team of developers independently
or replaced as a unit when the business needs change. It could be from a reuse point of
view--what elements could be usedelsewhere in the application? Or maybe from a
user experience point of view--what elements are visually related on the screen? What
elements will be routed together keeping in mind any secondary or child routes or
named routes in your application? And, last, we'll cover this more later when we talk
about Angular's change detection--what elements are going to be changing or not
changing together? Those are each valid reasons to lump pieces of your
application together in a component and have other pieces in other components. How
you weight each piece when it comes to your component breakout is up to you and
the needs of your application. I know this guidance is a little vague, but the important
thing is that you go through the exercise of thinking about where yourcomponent
boundaries should be. As long as you make a conscious decision about it and know
why you chose the boundaries you chose, your answer is likely not wrong. For
example, I would rarely, very rarely have a component be just a single form field or
DOM element. But I can think of scenarios where each of those could be the right
answer.

@Input Decorator on a Property Setter

Let's talk about ways we can cross those boundaries. The easiest way to pass data from
one component to another is a simple input property. We've all seen and probably
used this, so I'm not going to go into details here. Just a simple declaration and usage
setting the cubicleId property to the literal string AA-23. This is all fine and dandy for
many use cases. But sometimes we need to take some action when a property is
changed. That's when we would typically use a property setter, and there's nothing
that stops us from doing so just because we're using an @Input decorator on the
property. Here's an example. In this case, when the cubicleId changes, we need to take
some action, namely, hydrate the correct person from the database. You'll notice that
we don't directly change the cubicleId value in this setter. There's some logic that
needs to happen, and under certain circumstances, the ID may not change. We handle
all of that in our hydrateDisplayPerson function. Passing a value into this
Input property is still the same. We've got a widget in our demo application, and it
makes use of this, so let's go take a look. So for this first demo, we're going to start out
just going through some basic stuff with a slight twist on how you would typically
handle input properties. So we go and load our widget, taking a look at an @Input
decorator widget. And it just has a button, and basically it's just switching from
one user to another. Pretty basic. Looking at the code for this starting in the
widget.component.html, you can see we have our person-component, and there's
where we pass inthe cubicleId into that component. And then we have a button
that just toggles from one user to the other. The code for that, pretty straightforward
again, kind of just making sure everybody's up to speed on some of these basics or
understanding what components are all about. We set our cubicleId to AA-23, and
then when we click the button, we just toggle that from either AA-23 to BB-08. The
interesting part happens inside our component. Inside the HTML, we just put out the
information to the screen, the person's name and the person's ID as we saw in the
demo. In the TypeScript file, you can see we have our Input property, but it's set on a
property setter. So this is the slight twist from what people typically use Input
properties for. Typically you wouldn't have a getter and setter, but I just wanted
to point out that it is possible. This allows me to keep separate from the widget
component. All that needs to be concerned about is the cubicleId. It doesn't need to
know how to get a full person, how to hydrate that person, how to do anything person
related. It just says, I want to show the person the information about the person who
sits in this cubicle, passed in the cubicleId, and then the setter for the cubicleId does
some extra processing. It's as if we don't have a currentPerson, or the
currentPerson's cubicleId is not the passed-in value, then we're going to hydrate that
DisplayPerson.And once that person is hydrated, then we're going to set
our currentPerson property to that hydrated person. And the currentPerson property
is what we work with to display out in the UI. Now hydrateDisplayPerson, nothing
special here. I have it just hardcoded. It's just flopping between Louise and Larry Smith
based on the cubicleId of either AA-23 or anything else. So like I said, this allows me to
keep separate the logic behind hydrating a person, and really anything to do with a
person other than the cubicleId is inside the PersonComponent. The
parent.component, the widget.component in this case, all it needs to know about is
the cubicleId. It says, Give me the information for the person with this cubicleId. We do
all of our work on the setter. And that's our Input property. So, again, pretty basic
component, slight twist on the how the Input property is set. I just want to make sure
that everybody's up to speed on the basics of all these pieces before we go further.

Checking for @Output Property Subscribers

The opposite of an @Input decorator is naturally an @Output decorator. The example


shown here is your standard output, nothing fancy about either declaring or utilizing
this. We're simply binding a function in our parent component to an event that we
raised in our child component. The interesting part is when we start to use the fact
that we may not have anything bound to our Output property to control aspects of
our component's presentation, like here where we're saying if nothing is bound to the
help emitter, don't display the text Contact Help Desk. The important thing to realize is
that we can confirm whether or not anything is listening to our emitter and modify our
presentation appropriately.This is especially handy when you're creating reusable
components and you want the ability to control the presentation based on the status
of an emitter subscription. In the example we're going to look at in the demo
application in just a moment, the error banner component is one that could be used
across multiple applications. Each application can decide if it wants to display the link
to contact the help desk simply by whether or not they subscribe to the help
emitter. That makes the component much more flexible and keeps control on
the parent component, which is where it belongs in this case.The help banner
component always displays the same user-friendly error message, and if the
application decides to, it can allow the user to ask for more help. Furthermore, the
help banner component doesn't need to be concerned about what the error is or how
to collect the information to pass to the help desk. All that's handled by the function,
which is subscribed to the help banner's Output property. Let's dig in to this further in
the demo. Continuing with some fairly basic stuff but with a little twist to at least spice
things up a little bit and make it a little more interesting while we're making sure that
everybody's on the same page with regard to components, we're going to take a look
at a basic @Output decorator, and to do that, I have this widget that's going to display
an error message. So I can toggle the error so that it's turned on. I've thrown the error.
Then I have this Contact Help Desk link here. And I can make that appear or disappear.
And it's probably not doing it the way that you think it is. So I can have the basic
error message if I don't have a handler registered. Or if there's something set up to
handle it, then it's going to show the Contact Help Desk. When I click on that, in this
case, it's just throwing up an alert. But this is code running back in the parent
component. That allows the error banner component to really do nothing but display
the information. It's up to the owning component, the parent component to figure out
what information needs to be collected and how to contact the help desk. So taking a
look at this in code, starting in the widget.component.html, you can see I have two
instances of my help-banner, and an ngIf is going to control which one gets
displayed. So basically the difference is it toggles based on whether handler is true or
false. The only other difference between these two is you can see the top one has this
help function bound to the Output property. The button is just toggling the error or
toggling the handler. I'm not going to show you those, they just flip back and
forth. Taking a look at the TypeScript file, you can see here's the code that gets called,
so it's in the parent component like I said. Taking a look at the help-banner, here is the
general message that is always displayed. And then below that is our Contact Help
Desk link. That's only going to show up if this showHelpDeskLink is true because of that
ngIf. And when we click on that link, it's going to call this helpClicked, so let's take a
look at the code for that. This is where things start to get a little interesting. So basic
component stuff, then we have our @Output decorator on the help property, and
that's an EventEmitter. We set up our HelpDeskLink Boolean. And then when that link
isclicked, then it's going to emit just like a regular Output property. It emits, and that's
what gets called back to here because this is the function that we have bound to that
Output property. But the interesting thing is this last line down here in the
ngOnInit. We're only going to show that HelpDeskLink, the Contact Help Desk, if
something is subscribed to our help Output property.

Manipulating the UI with Directives

Next up, we're going to talk just a little bit about directives. As you're most likely
aware, there are three types of directives-- components, attribute directives, and
structural directives. If you're not aware of components being directives, well, they
are. They're just directives with a template, which is kind of cool if you think about it.
We already touched on components, and we'll do so much more throughout the
course. So there's really no need to cover them now. I'm assuming you're already
familiar with the standard structure directives in Angular--ngIf, ngFor, ngSwitch--and
there's really only a few other UI-related things that we're going to cover later in the
course. So for now, we can cross those off too. That leaves attribute directives, which is
what we're going to talk about next. In a nutshell, this is what an attribute directive
does. But this simple statement can be deceptive. Why would we want to change the
appearance or behavior of a DOM element via a directive? We'll look at a specific use
case in a moment and more throughout the course. But, first, here are a couple of
general thoughts. These are all variations on a theme, but I think they help. Directives
can make your HTML more dynamic. In one application, I have a scenario where users
may or may not have access to certain parts of the application depending on which
license they purchased. A directive allows me to easily alter the DOM for this. Now I
use a router guard to actually keep them out of the areas they haven't paid for, but the
directive allows me to put something in the UI that tells them there's a paywall before
that functionality. The goal of most applications is to present the UI the user wants
or needs, and that may change from run to run. Directives allow us to respond to
environment changes. Using the same scenario as above, if the user enters a valid
license key in the middle of a session, the directive is no longer going to modify the
DOM to indicate the paywall. But I didn't have to change anything in the code. I just
had the directive there. It just doesn't apply anymore. And last but not least, directives
are just so darn easy. Litter the attribute directive across your UI wherever you need it,
and the logic for it is all centralized in one place. In that same application as above, the
directive could be on a dozen or more elements on a page. Adding a directive was
easy, and I don't need to think about where all that logic is. It's all together in one
place--the directive. So those are some general thoughts about the usefulness of
directives. Let's go take a look at how the use case I mentioned is actually
implemented.Hopefully this will spur you to think of your own cases for custom
attribute directives. Taking a look at a quick little demo to show directives updating
our UI, we'll load our last widget here, and you can see it's essentially an adaptation of
a paywall directive that I have for a product that I've built. And what it's doing is
looking to compare a user's current license to a required license for a certain piece of
functionality. If they don't have the appropriate license, then it throws this
little indicator off to the right, and it says Requires additional license purchase. Now I
have this set up here just for simplicity's sake. Everything is randomly generated, so
every time I load this, the directive displays next to different pieces. But the idea is that
it's checking some condition and then updating the UI. And I can put this directive, in
fact I did put this directive, all throughout my application to check licensing. As I said in
the slides, I actually control access or restrict access with route guards, but this gives a
nice visual indicator to the user that, Hey, you're not going to be able to get
here. Taking a look at the code for this, pretty straightforward. A simple unordered list
of links, we use our hsPaywall directive. And another important thing to note there is
that we do prefix that with some unique set of characters so that it's not just
Paywall. That avoids any potential conflicts if I'm using third-party libraries or anything
like that. We pass in the requiredLicense, which is just a property of the individual
item, and display the title all as part of a link. Inside the widget.component, I'm
generating a list of links and randomly assigning a licenseLevel to them between 1 and
3. That information gets passed into my paywall.directive via an Input property. Don't
worry about the details here. We haven't talked about some of the details like
Renderer2 and ElementRefs. I really just wanted to put this in front of you and show
the purpose behind directives, updating the UI in this case based on certain
conditions. You could have directives that update the UI in every case any time it's
used. But here I'm applying a condition. Specifically in my checkLink function, I'm
checking if the requiredLicense for a particular element is greater than the
currentLicense the user has, which is stored in a configuration service. Then I'm going
to put that little dollar sign next to the link.

Altering Data Presentation with Pipes


This is about the simplest definition of a pipe I could come up with. It's just important
to note the only part at the end. Pipes don't actually change the data in your
components, just the way it's presented on screen. Mostly what I want to make sure
you're aware of is which pipes are available to you from Angular out of the box. I've
broken them out into three categories based on their current status.Starting with the
ten most common pipes, these are all currently stable, meaning that you could use
them without expecting many of any changes as Angular matures. I've included the
descriptions for each of these straight from the Angular site, and most of them are
pretty straightforward. You can figure out what each does simply from its name. If
you'd like to read up more on these including seeing details and some examples for
each, you can use the URL at the bottom of the slide. Just drop the name of the pipe in
at the appropriate place. The next category of pipes is those that are tagged as
experimental. Both of these are used for localization. You can expect to see
some changes to these as they eventually make their way to stable. And, finally, four
pipes that while not officially deprecated yetare likely to be soon, something about the
new name they were each given seems to have given that away. They've each already
been supplanted by a corresponding pipe from the stable category. The difference
between these and their stable cousins is that these require the use of the
internationalization APIs, which are not available in all supported browsers and so may
require polyfills,whereas the stable ones don't have that requirement. As I said, these
aren't officially deprecated yet, but their names have been changed, which is a bit odd,
so the writing looks to be on the wall for them. They're still available, though, so you've
got a little more time to use them if you choose before they disappear. My advice,
though, would be don't start using them now if you're looking to add localization to a
project. Use the stable flavors. Just a couple of things to know about pipes. They're
chainable so you can use multiple simultaneously. In this example, we're using the
date and uppercase pipes to produce the final output. Second, pipes can accept
parameters. In this second example, we pass a format string to the date pipe to control
how the date is formatted for display. Pipes can take multiple parameters too.
Typically separate successive parameters with colons, but sometimes a single
parameter is made up of multiple parts, so you need to pass in a specially formatted
string. In this case, check the documentation at the URL shown on the bottom of the
previous three slides for the exact format each pipe expects. And the last thing we'll
cover here is the distinction between pure and impure pipes. This is a little more
complicated than the first two, so we have a whole discussion on this later in the
course when we talk about performance. For now, just know that most of the out-of-
the-box pipes are pure and so have little impact on performance. When building
custom pipes, you want to try very hard to keep the pipes pure. Again, we'll go into
more detail on what that means in the section of the course on performance.

Wrap Up

A quick summary of what we covered in this section of the course. A lot of this may
have been review of some basics for you, but hopefully you picked up a few
capabilities that can help you build out your user interfaces. At this point, everyone
should be at least familiar with these basics so we can move on.Much of what we're
covering in the rest of the course builds on these basics, so it's important to make sure
you've got these down before continuing. Up next, querying the UI. We're going to
look at how you can get access to UI elements while still maintaining separation of
concerns and a loosely coupled architecture.

Querying the UI

Introduction

In this module, we're going to look at different ways we can get access to the elements
in our UI so that later we can start to manipulate them. The topics we're going to cover
are shown here. We're covering the most common ways to query the UI, as well as
the items Angular uses to represent DOM items or to work with DOM items.

Templates and TemplateRefs

First, an easy bit. Templates are our HTML. There are three ways to define these in
Angular, and if you haven't seen all of them, here are some simple examples. I think
that only the third one, ng-template, may not be familiar to everyone, and that's okay.
We're not going to cover it extensively here. We'll just see it as part of some other
things we're focusing on. But we'll cover ng-template in much more detail when we get
to the section on dynamic components later in the course. But for now, just know that
it's essentially a named chunk of UI that won't display until we specifically tell Angular
to show it somewhere. We'll go much deeper on it later. I just needed to put these in
front of you again so that we would have something to point to when we moved on to
TemplateRefs. Here's the official definition from the Angular website, but this is about
as useful as decaffeinated coffee. It's actually much simpler than that definition sounds
though. An TemplateRef is a reference to one of these things. This is technically an
embedded template, as opposed to these other two types of templates that we've
seen.While I have this back on the screen for a moment, don't do this. Do this. Inline
templates once they get past a couple of lines are just harder to work with, and the
lack of explicit template files is going to confuse someone at some point, even if just
for a few moments. It's better just to avoid it right from the beginning. One more basic
thing, I just want to make sure that everyone is familiar with template reference
variables as we're going to be using them throughout the rest of the course. In my two
examples shown here, I have a template reference variable defined myClass, a variable
reference in the div, and tmplA, a variable reference in my ng-template. Now we can
move on and begin to look at some more fun stuff.

Querying the UI via ViewChild(ren) and ContentChild(ren)

There are four common ways to get a TemplateRef, and they're all variations on a
theme applied to a property via a decorator. Which one you use depends on two
things--how many templates you wantto retrieve and where those templates are
defined. Let's take a look. Two of them, @ViewChild and @ContentChild, are used
when you want only the first item matching your selector. These return a single
TemplateRef. We'll get to selectors in a bit. The other options are for when you want
to return multiple TemplateRefs. @ViewChildren and @ContentChildren return a
QueryList collection ofTemplateRefs containing each TemplateRef that matched your
selector. We'll also cover working with QueryLists in a bit. Let's first take a look at the
difference between content and view With regard to retrieving TemplateRefs. There're
essentially two places you can define a template, and which of those places you
use determines which decorator you use to retrieve the TemplateRef. Starting with the
child decorators, this code is from inside a parent component, in this case one called
my-component, but it could be any component. Here we have two templates defined--
TemplateA and TemplateA2. From the point of view of my-component, these are
content as they're inside the my-component tag, so I would access them with
@ContentChild or @ContentChildren. Now here's the code from the my-component
template file. Again, we have two templates to find. This time, though, again from the
point of view of my-component, these templates are inside the view. So we access
them with @ViewChild or @ViewChildren. Taking a look at this over on our demo
machine, the thing that I want you to get out of this demo is the distinction between
view and content with regards to our child component. So we have a simple demo set
up here that defaults to showing the view template--you can see this is content that's
defined inside the child component's template and queried with @ViewChild. We can
click the button to toggle over to showing our content template, which is queried with
@ContentChild.So pretty basic, but let's take a look at how we got this in the
code. Starting in our Child Component because this is where everything is referenced
from, everything is from the point of view of the childbecause that's where our code is
running. We scroll down, we have two of our decorators here. We have the
@ContentChild going after a template reference variable of content and @ViewChild
using the template reference variable view. We're binding to this liveTemplate, which
just represents a TemplateRef. And then when we click the button, all it does is toggle
this Boolean and then use that todetermine whether we show the view template or
the content template. So pretty basic. Like I said, the important thing is, What is
view? And what is content? So looking at our Child Component, we can seedown at the
bottom here we define an ng-template with the template reference variable view. This
is our view content. It's inside the Child Component's template or inside it's view. We
query it with @ViewChild. Going up into our parent widget component, we can see the
declaration of our child right here, and inside that, we define another ng-template
using the template reference variable content. This is where our content template is
defined. So inside the declaration for our child, that's considered content from the
child's point of view. Inside the child's view, that's considered view content. And,
again, looking at our basic demo, we can toggle between the two. So feel free to
explore this code and get a sense for what's view content and what's content content.

TempateRef Selectors

Selectors are what you use to tell Angular which TemplateRefs we want to work with.
And you pass them into the decorator. These options also apply when you're working
with ElementRefs, which we'll see later. But for now, we're going to focus on
TemplateRefs. With selectors, you can use template reference variable names. These
get passed as a string, and you can specify multiple by just separating them by commas
in the passed string. You can also use types. Since we don't assign types to
specificTemplateRefs (they are after all just chunks of HTML), the only one that makes
sense here for TemplateRefs is the TemplateRef type itself. As we'll see in the demo
shortly, we can use this to grab allTemplateRefs defined in a given place. Each of the
decorators we've discussed can take a parameter specifying different options to allow
you to fine tune your query. Unfortunately, neither of the options are particularly
useful when working with TemplateRefs. I'll mention them here and explain why they
don't help, and then we'll look at them again when we get to ElementRefs where they
do come in handy. All of the decorators allow you to specify the read option. Read
allows you to specify exactlywhich token is returned by the query. For working with
TemplateRefs, reading something other than the TemplateRef token doesn't really
make any sense, so there's no sense in overriding it from the default, which is
TemplateRef already. The other configurable option is descendants. As the name
implies, this setting controls whether or not the query looks at just direct children of
the source element or at all descendants. This option is only available on the
@ContentChildren decorator, but setting it when working with TemplateRefs doesn't
actually do anything, so not much help here. The only other thing you need to know
about selectors is that they are live. If something changes in your application and the
selector now returns something different, your variables will get updated. Taking a
look at the different TemplateRef selectors available to us, going to our next widget,
and all this is going to do is show the counts of the different templates that we have in
different places. So let's go take a look at the code that we use to get these
counts. We're going to start over here in our widget.component, and we're declaring
just a simple Child Component. And inside that, we declare three different content
templates. Taking a look at the Child Component itself, down at the bottom here, we
declare another collection of templates. We use 1, 2, and 3. In the code for the Child
Component, we're using our @ContentChildren selector to go and get all of
the TemplateRef types in content. We store them in allContent. We use
@ViewChildren again with the TemplateRef type selector to get all of the views. And
then we use the @ContentChildren again. This time we're using our named template
reference variables. So these are the two different ways that you can query
for TemplateRefs either using a type of TemplateRef, which is going to give you all of
them in a given area, either view or content, or you can go in and specify a template
reference variable or, as we're doing here, multiply template reference variables
separated by commas. So jumping back over to the demo, you can see we have three
content children--that's these three here. We have four view children, and this is a
little different. We've declared three of them here, but this entire file is a template as
well. So that's the note on the end here, it includes the Component template for our
child as well. And then we have two templates in our someContent variable.
SomeContent is our last @ContentChildren where we're using the named template
reference variables. Those are the different selectors we can use for grabbing
TemplateRefs when we need to work with them.

ViewContainerRefs

We've now seen how to get a TemplateRef, and we've said that we can use
TemplateRefs to stamp out a dynamic number of copies of the contents of the
template referred to by the TemplateRef, but where can we stamp out those copies?
Anywhere in the UI? Well, sort of. We're going to be looking at injecting
TemplateRefs later in the course, but before we can get to that, we need to discuss
ViewContainers and ViewContainerRefs. Like templates and TemplateRefs,
ViewContainers are the thing, and ViewContainerRefs are the references to them. In
this case, ViewContainers are the places where we can inject our TemplateRefs, but
here's the thing, they're slightly misnamed. Views don't go inside ViewContainers
when we add them. Instead, they go next to or after the ViewContainer, not generally
a big deal but good to know. Let's go see that in our demo application. Let's take a look
at how we can go about getting a ViewContainerRef and a little bit about what we can
do with it once we have it. So we'll go into our ViewContainerRef widget. We've got a
couple of buttons across the top here, and it's just going to give me the ability to add
instances of my templates. So I can add a couple of instances of Template 1. I can add
Template 2. And then if I want to, I can go ahead and clear out Template 1, and go
ahead and add it in again. The code for this, we're going to start in our
widget.component, and we're going to declare a couple of divs with TemplateRef
variables of vcr1 and vcr2, vcr for ViewContainerRef. And then we just define a couple
of templates down at the bottom here, t1, t2, and t3. Up at the top, we have our
buttons that call addTemplate1, addTemplate2, and clearVCR1. Taking a look at the
code, you can see that we're using all @ViewChild in this case. We're going and getting
vcr1 using the template reference variable, and we need to explicitly state that we
want to read the ViewContainerRef. So for vcr1 and vcr2, we explicitly state with our
read option that we want the ViewContainerRef. @ViewChild to get t1, t2, and t3 just
like we've seen before. And then we have the code that actually starts to work with
our ViewContainerRef. So when we click the addTemplate1 button, we're calling this
function right here, which uses the vcr1.createEmbeddedView to simply
show template 1 inside or actually next to that space. We'll take a look at that next to
in just a second. Same thing for template 2. We're creating an embedded view using
t2. We can check the length, and we use that to either enable or disable our button for
clearing. And then clearing itself, we just call the clear function. We'll take a look here.
There are a bunch of other functions available on our ViewContainerRef. Most of them
are pretty straightforward. Some of them we're going to take a look at a little bit later
in the course. But you can see as we saw, we can check the length, we can
movetemplates around, we can check the index, we can get different templates or
different views inside that view container. Now the last thing I want to do is jump over
and bring up the dev tools. Here is my ViewContainerRef widget. Let's give ourselves a
little more room here. Go down through my buttons, and I have my div. This is my---
let's see if I can make this a little more obvious. Here's my div that is my
ViewContainerRef. When I actually inject or create the embedded view, it doesn't
go inside that div, it goes after it or next to it. So that's a little bit different than you
might expect, but the effect is the same.

HTMLElement as ElementRefs

Like a TemplateRef, an ElementRef represents a piece of your UI. Unlike a


TemplateRef, an ElementRef represents just a single DOM node or element. Working
with ElementRefs is similar to working with TemplateRefs. You still have the same four
query decorators. You still query your HTML using the same selectors. You have the
same options available. And the results of the selectors are still live. Since we already
covered a lot of this in TemplateRefs, we're just going to focus on where things are
different for working with ElementRefs, which for all intents and purposes is just in the
area of the options. So that's what we're going to spend our time on. As a result of the
capabilities we can now actually put to use in the options, we do have some additional
capabilities in some decorators in how we specify some selectors, but we can see all of
that in action when we dig into the options. The options themselves aren't any
different. We still have read and descendants, which we discussed earlier. The
difference is that now we can actually use these options for something.

ElementRef Selector Options - Read

Let's start by looking at the choices for the read option. There are four values that can
be passed into the read option. Which one we use depends on what object matches
our selector and what we're trying to retrieve. And we'll cover those scenarios in just a
minute. But, first, the four options--ElementRef, ViewContainerRef, TemplateRef, and
Type. Specifying your read option is a simple matter of adding a JSON object parameter
after the selector and the decorator. Here's an example of a decorator with no option
specified. And as you can see, it gives us back the component instance itself.Adding a
read option as shown here changes the return value from the query to now give us the
ElementRef for the element in the UI. Because we're using @ContentChild here, we
only get back the first thing found. Without explicitly specifying what you want back via
the read option, the type of the return value depends on what you ask for. Use a type
as your selector, you'll get back a type instance.Use a template reference variable for
an element, you'll get back an ElementRef. The read option lets us override that
default behavior. Also if you want to get back a ViewContainerRef, you'll need
toexplicitly state that via the read option. You can't get one back without doing
that. Let's go take a look at some other examples in our demo. Taking a look at the
different options available to us for the readproperty, two quick things we need to look
at first. We have here the TypeScript file for our Child Component, and we just need to
see that it contains a Prop1 property with this value. We'll be seeing that when we do
our selections. Taking a look at our widget.component, we're setting up the elementfor
our Child Component, and it has a template reference variable of child. Above that, we
have a simple HTML div with a template reference variable of title. So these are the
two things that we'll be grabbing with our selectors. The selectors themselves are over
in the widget TypeScript file. You can see we have two @ViewChild decorators here on
our properties. The first case, we're going and grabbing by type. The second case,
we're grabbing by template reference variable. We're going to get back the same
thing. We're going to get back our actual ChildComponent itself storing them in child
and child2. Taking a look at this just really quickly in the demo, here's our widget,
here's our Child Component. Now we're just writing the properties or the things that
we've selected out. So you can see we're getting when we select by type, we get the
actual component. Here's the Prop1 property that we saw on that component. Same
thing when we select by reference variable, we get the actual component itself. Now
let's jump back over and start to change some of that. So we're going to uncomment
these couple lines here and down inside our AfterViewInit. Go ahead and save
that. And now what we're doing is we're still going out and grabbing by type or by
template reference variable, but we're specifying that we want the ElementRef, so
we're getting a different token. We're saying give me the ElementRef instead of the
actual ChildComponent itself. And you can see that's the type that we have out
here. So we're going to do two different things. We're going to write that into the UI,
and then we're also going to write them out into the console so that we can explore
them a little further.Jumping back over to the browser, going into our widget, here we
now have selecting by type, but we're forcing the ElementRef, and that's what we get.
The only thing available on the ElementRef is our nativeElement. We will be exploring
this later when we talk about manipulating the UI. We'll be looking at nativeElement a
lot more closely. But the same thing when we go and get it by reference variable,we're
forcing the ElementRef, and that's what we get. Taking a look in the console, you can
see we get our two ElementRefs, and the nativeElement is our Child Component or the
element that represents our Child Component. So two different copies of the same
thing. Jumping over to the code one more time to look at option C, in this case, we're
going and grabbing that div that has the templatereference variable of title. Now we're
grabbing it two different ways, but we end up with the same thing. In the first
case, we're going and grabbing it just with the template reference variable, but we
don't specify anything for the read option. In the second case, we still go and grab it by
the template reference variable, but we specify a read option to force the
ElementRef. But like I said, in either case, we end up with an ElementRef. That's
because the default when you're grabbing an HTML element is the ElementRef. In this
case, we just log these out to the console. So let's jump back over to the browser and
take a look at them there. Go into our widget. And here we need to take a look at
things in the console, but you can see we're selecting by reference variable both
times. The second time we're forcing the ElementRef. What we get each time is an
ElementRef, though, because even though weselected and didn't specify, we're getting
the HTML element, which is represented by our ElementRef. Both of them really point
to the same thing even though we went and got them different ways. So what you get
depends on your selector, what it is you're selecting, and what you specify in the read
option.

ElementRef Selector Options - Descendants


That takes care of the choices for the read option. Let's take a look at descendants
now. As you would expect, the descendants option allows us to specify whether or not
our query will search through all descendants or just immediate descendants. In either
case, the starting point is always the current component, the one where the code is
running. The thing about the descendants option, though, is that we can only use it in
one situation. For @ContentChild, @ViewChild, and @ViewChildren, the descendants
option defaults to true, and there's nothing we can do to change that. This means that
our search using these decorators will always search through all descendants of our
starting point, an important thing to keep in mind or else you may not get the results
you expect. It's only with @ContentChildren that we can specify a descendants value
to override the default, which in this case is false. So if we don't specify a descendants
value, @ContentChildren will search only our starting point. Overriding that to a value
of true will cause it to search through all descendants. Specifying a value for
descendants is nearly identical to specifying a read option, a simple JSON object after
the selector. Specifying both read and descendants options is simply a matter
of specifying both in the JSON object. If you try to specify the descendants option on
ContentChild, ViewChild, or ViewChildren, the TypeScript compiler's going to yell at
you. The descendants property is not available for those. Working with the
descendants option can be a little bit confusing just because there are so many
different permutations that you could end up with. So let's take a look at our widget
for this, and you can see there's a fair amount going on here. I have my widget in blue.
I have my Child Component here in kind of a tan. The Child Component as part of
content contains a Child3 Component and a Child4 Component. As part of its view, it
contains a Child2 Component, which then contains a Child3 Component as part of
its content, and another Child3 Component as part of its view. And then we're jumping
back to the Child Component, and as part of its view, it's also containing a Child3
Component.Now you can see that what we're ending up with is just some simple text
that shows up that says, How are these different things being selected? So the Child3
Component up top here is being selected viaContentChildren, as well as
ContentChildren when I specify the descendant. Child4 Component is only being
selected via the descendant option on ContentChildren. You can see each one has a
location, and that's being used to kind of keep things straight so we can see what gets
selected when. So starting with this kind of quick overview of what the outcome
is, let's go take a look at the code. We start in our widget.component, and it defines
our different Child Components in our locations, and we give them these location
input property values, so we have A and B. They're declared inside my Child
Components, so they are content to the Child Component. And you can see that we
have a Child3 Component as location A. Nested inside that, we have a Child4
Component as location B. Jumping over to the Child Component itself, we're declaring
a child2. Inside that is a child3 with a location of C.And then we also have as part of the
view on the Child Component location D as another instance of child3. Now this one
never gets selected, but it's just kind of here to show you that nothing selects this,
nothing goes into Child2 Component and looks at its view. So location E is never
selected. Close that out to get it out of the way. The code itself, pretty straightforward,
we're using @ViewChildren.@ViewChildren by default is going to look at
descendants. So we'll see that when we get into it. We have a couple different options
for @ContentChildren, sometimes with descendants set to true and sometimes with
descendants not set to true. Down at the bottom here, we just have some code that
runs and takes a look at what we get in the QueryList, and we'll take a look
at QueryList in more detail actually next part of the course. But we'll take a look at that
in just a few minutes. But it goes through the different output from my selectors and
just sets a variable that determines whether it gets put up on the screen. So jumping
back over to the browser, you can see again what the output looks like.Depending
upon my selector, different things are going to show up as having been selected either
as content or as views. In the code, that corresponds with what I'm selecting here, so
my viewChildren, my contentChildren, a second look at contentChildren going after my
Child3Component, and then a third going after my Child4Component. Now each of
these have descendants set to true. @ContentChildren by default doesn't look at
descendants. @ViewChildren does, @ContentChild does, @ViewChild does. And to
show you that, let's go ahead and grab this one here, and I'm just going to do some cut
and paste coding. We're going to change this to @ViewChild. You'll notice we get
an error here as soon as we change this that says that we can't specify descendants for
contentChild, it's not available, so we need to take that out. I'm going to call this
contentChild, and it's not going to give me a QueryList. Instead, it's going to give me
my Child4Component. I'll clean that up just a little bit, and then I need to take this, and
we'll go down here. So what we're doing is setting another one of these properties
that's going to now show this as being selected. Now what we're going after here is a
@ContentChild of type Child4Component, SODChild4Component. Taking a look at
our declarations here, we can see that what we're going after is this Child4Component,
but it's nested inside of the Child3Component. It is not a direct child of my Child
Component. But we can't specify as we saw, we can't specify descendants true
here because it's not available to us. But that's okay because@ContentChild like
@ViewChild and @ViewChildren by default is going to look at descendants. It's only
@ContentChildren that allows us to specify descendants being true. So let's go ahead
and save this. Jump back over to our browser. Take a look at descendants, and we can
see what that's gotten us is this nested component has in fact been selected by
ContentChild. So it is going down even though we didn't specify descendants, even
though we couldn't specify descendants, it is still queried. So I recommend that you
spend a little time with this. Take a look at this code, play around with it just to start to
get an understanding of how I query different things and what the impact of specifying
descendants is in different scenarios.

ElementRef via Dependency Injection

One other approach for getting an ElementRef from the UI is to use Angular's


dependency injection. If you have a component declared like what you see on the
screen here, and in the constructor you inject an ElementRef, you're going to get a
reference to that element defined by the component. We're not going to take a look at
this in the demo right now. Everything you need is on the screen here, and we're going
to be using this to our advantage later when we talk about directives, so we'll see it
then.

QueryLists for Collections of UI Items

We've seen code like this, which will pull all instances of our CompCComponent
reading the ElementRef for the UI element instead of the CompCComponent itself and
store them in a variable named allC. AllC is a QueryList of ElementRefs. Each item
inside the QueryList is another ElementRef that matched our selector. If no items
match the selector, we'll still have a QueryList in allC, it'll just be empty. A QueryList is
like an array but not identical. If we need an array, we can cast it to one using
toArray. There's a bunch of other interesting capabilities we have with QueryList
including subscribing to changes, so let's go see how we can work with QueryList in
code. Taking a look at the QueryList, and I realize that we've seen this before in some
of the other demos, but we're going to dig into someof the more interesting pieces of
this in this particular demo. So looking at the UI, you can see we just have a collection
of books and a couple of buttons. Jumping over to Visual Studio Code, here's how we
got that. Here're our buttons. We'll take a look at what each of those does. And then
we're simply going through and iterating through an allBooks collection using ngFor
and spitting out just the title, the author, and the genre. So that's going to get
repeated. Each one gets assigned the ID property of the book itself. So back over here,
that's the output that we saw. I can go ahead and click on this Science Fiction, and it's
just going to put a little red border around the books that have a genre of science
fiction. To do that, we're actually querying the UI. And so we're going and taking a look
at some of the code. We have our allBooks collection. I have a Book object. It says ID,
author, title, and genre. We have our query. Here we're going in and saying, Give me
everything with a template reference variable of book, and we're going to store that in
this books. It is a QueryList of ElementRefs.We'll come in and take a look at the
subscription. We do an ngAfterViewInit in just a moment, but the button that I
just clicked on is going to be calling this filterByGenre, and it passes in the genre, in this
case, I used science fiction. So what we did here is we actually filtered the
QueryList. So books is our QueryList of ElementRefs, and we say go ahead and filter
that by applying this function to each of the items inside that QueryList, and give me
back the things that match, in this case that my genreMatches function returns true.
And the code inside genreMatches, you can take a look at that, it's not really
relevant. The fact is I'm applying a filter to my QueryList. I can then go through and call
forEach on the results. And we haven't taken a look at Renderer2. We'll take a look at
that in the next module, but we can use that, and all that's going to do is put my red
border around anything that matches this filter function. So that's using the filter
capabilities of my QueryList. Jumping back over, let me just clean this up a little bit so
we start fresh. I'm going to go ahead and add a book. So I've got a new book
added down at the bottom here. Now what you'll see when I go into the console is that
we have a new item added down here. Here is my book that was just added. If I go
ahead and click this again, we now have seven books. Click to add, and it's writing
out basically the contents of my QueryList. So every time I click that, this is being
added. Jumping over to the code, that's happening here because I'vesubscribed to the
changes observable of my QueryList. So every time that a new item is added or
removed, this observable is going to fire, and it's going to give me actually the
QueryList itself. So it doesn't give me just the differences, but it will be relatively easy
to dif this to see what was in their before and then dif it and find out what were the
new things that were added or removed. So all I'm doing is taking that, calling another
function that's available on QueryList, toArray, to write the array of those ElementRefs
out into the console. You could do whatever you need with them. But, again, I can
subscribe to the changes that happen in the UI. So that's not actually firing when I add
my book. So I could actually fire it here, but if I don't have control over that, if I'm not
the one that's running the code that's injecting a new book, well, this gives me another
option for reacting to something changing inside my UI. All this is doing is adding a
book into the allBooks collection. The allBooks collection is what is iterated in my
ngFor. So when I add a new book, the ngFor is going to refresh the UI and put the new
book information in. That's what's going to fire this changes observable. Same thing if I
jump over, clear us out again, and I start removing books. You can see that as I do, it's
writing out what's in the QueryList, and then it's going down as I remove each element
out of the QueryList. So that's filtering, iterating that collection, calling
toArray, subscribing to changes on my QueryList, and some of the more interesting
capabilities of what you can do. If we want to take a look at the IntelliSense, you can
see some of the other possibilities. We looked at filter. You can do find. You can get
first and last. You can get length. A number of different capabilities for retrieving items
out of your QueryList, which is really working against the UI. It's not working against
your back-end data. So, again, if you don't have control of your items being added
into the back-end data, all you can do is inject something at the UI point of view, here's
how you can respond to that.

Wrap Up

Here's a quick look at all the key things we covered in this section of the course.
Templates are sections of our UI which aren't displayed unless we specifically tell
Angular to show them. And we're going to take a look at these a lot more in the
dynamic UI module. Refs are pointers to different constructs. We looked at
TemplateRefs and templates, ElementRefs, and elements, and also ViewContainerRefs
and ViewContainers. We looked at querying our UI with the four available query
decorators, two of which return the first matching item, two of which return
a collection of all matching items. We looked at fine tuning our queries with different
query selectors and the read and descendants options. And, finally, we looked at
working with the collections returned by ViewChildren and ContentChildren as a
QueryList object. In the next section of the course now that we know how to query the
UI to get connected to items within it, we're going to look at changing those items and,
therefore, manipulating our UI. We're going to do it all without jQuery.

Manipulating the UI

Introduction

In the previous section of the course, we looked at how to query the UI to get access to
elements in our DOM. Now we're going to take a look at how we can go and change
the DOM and, therefore, our UI, the Angular way, which means maintaining separation
of concerns and loose coupling. We're going to start with some easy low-hanging
fruit--a look at view encapsulation and the ominously named shadow piercing, which is
a little different from the rest of what we're going to talk about but still a means of
modifying our UI. Next, we'll take a quick look at building custom pipes and then
directives, which will be our lead-in to the real meat of this module--the proper way to
manipulate the UI in Angular using nativeElement and Renderer2. We'll finish off with
a discussion and demonstration of why jQuery doesn't belong in an Angular project
and how we can do everything we need to do without it. Let's get started.

View Encapsulation

View encapsulation defines how our CSS is applied to components on our


page. Imagine this is our page, and it has four components. When we define CSS
selectors, view encapsulation controls where on our page those selectors have an
impact, for example, affecting three of our four components. You can control how this
happens by setting the view encapsulation property on your component. Before we go
any further, we need to take a short detour to discuss shadow DOM. We're not going
to dive deep into the bowels of shadow DOM, just a quick overview, enough so that we
understand how it applies to Angular and view encapsulation. In fact, I'm going to
focus really on just one aspect of it--DOM isolation. Without shadow DOM, the DOM of
your page was a single monolithic thing. Any CSS selectors on the page applied to the
whole page and everything in it. The terminology reflected this. People spoke of the
DOM or the page DOM. And all kinds of silly problems arose with conflicting CSS
selectors and weird JavaScript written to filter out undesired elements. The important
designation in CSS was one attempt at remedying some of the problems presented by
having a single DOM. With DOM isolation, that all changes. We no longer have just
the singular page DOM. Now we can have individual component DOMs. Together
these component DOMs make up the page DOM, which does still exist, but we can
deal with the component DOMs individually. With that aspect of shadow DOM
understood, now we can discuss the options for view encapsulation. There are three
options for viewencapsulation in Angular. Emulated--Angular's going to
force encapsulation even if the browsers don't support it. Native--Angular's going to
rely on the browser's built-in support for encapsulation. And none--all encapsulation is
turned off. Emulated is the default, and you've seen this even if you didn't know what
it was you were looking at. Emulated is what causes Angular to add attributes like this
to the elements in our DOM and also to rewrite our CSS to add specificity to our
selectors forcing them to only match elements within our component scope. Native
and none do not make any changes to our markup or CSS because native is relying on
the browser's built-in support for shadow DOM andnone is not using shadow DOM. So
in each case, no modifications are necessary. The effect of all this on our CSS and our
markup is as follows. Starting with a component inside a page each having defined
styles, emulated allows the CSS to find in the page typically in our globalstyles.css, but
potentially in any stylesheet referenced directly in index.html or Angular.cli.json or any
styles added directly in index.html. These are going to pass freely into our
component. However, styles in our component are prevented from impacting
anything outside of our component's scope on the page. Starting from the same point
with native, external CSS from the page is prevented from impacting elements in our
component, and styles in our component are prevented from impacting elements
outside the component. In late 2017, the only browser with any real support for
native shadow DOM is Chrome 60 Embedder. With view encapsulation set to none,
external page CSS is allowed into our component, and our component CSS is allowed
out to impact the page. Let's go take a look at this and see how and when we can use it
in a demo. Taking a look at view encapsulation, I have a somewhat contrivedexample,
but I want to use it to show you both the capabilities of changing the view
encapsulation, but also the repercussions of changing it. So if this covers what you're
trying to do, then it's a good thing. If it happens as a side effect that you weren't really
expecting, well, then it's something you're going to have to deal with. So what we have
on the screen here are two different widgets. We have View Encapsulation and View
Encapsulation 2. Inside View Encapsulation, we have a parent component with a
colored block inside it. The block is green. All the blocks are green. We also have a child
component above that with the colored block. And then over on the right-hand side,
we have a totally separatewidget, a totally separate component not really in any way
related to the one on the left that also has another colored block in it. Now my
requirement is that in certain situations, I need to change all of these colored blocks to
a different color, we're going to say blue. I want to be able to do that as quickly and
easily as possible, so let's jump over and take a look at what I think is a
pretty straightforward, pretty easy way to go about doing this. I can come in here, and
I'm just going to uncomment this additional child component, go ahead and save, jump
back to my browser. Now I'm going to reload those widgets, and you can see that all of
my colored blocks have switched to blue, which is exactly what I want. By adding that
second component, I've said in this situation, I want all the colored blocks on the page
to be a different color. So how did I do that? All I did was include as you saw this
second component. That second component includes the CSS rule that changes
the background color all the colored blocks to blue. The way I got that to apply to all of
the colored blocks on the page was by changing the ViewEncapsulation setting for that
child2.component. I changed it to ViewEncapsulation.None. And you can see this is
how we go about changing it. It's in our component decorator. We say encapsulation:,
and then the encapsulation that we want. And by setting it to None, what that's done
is it's basically taken this CSS rule and put it unqualified into the page. So it doesn't
have anything that's going to say this only applies to child2.component. It now applies
to everything on the page. Because all of my other components are still using the
default view encapsulation, they're going to accept any CSS from the page itself, which
means that by simply having that on the page, I'm going to change all of the colored
blocks. Now if I were to go and reload this page for a second and load View
Encapsulation 2, you can see that one's going to be green, so until I go and load
something that has that page-wide rule, it's not going to come into effect. Now you
could say, well, there're other ways to do this, and sure there are. I could write some
code that says go out and find all the coloredblocks and change their background color.
But now I've got code that's running. Bu doing it this way, I'm letting the browser do
it. The browser says this is a CSS rule that applies to the entire page. Here I've got a
component on the page that matches that rule. The browser's just going to apply it. I
don't need to write any code specifically for that.

Shadow Piercing - Bypassing Shadow DOM

All that's great and all, but sometimes there're legitimate reasons why you'd need to
change that behavior and may not want to or may not be able to change the emulation
setting on your component. So what do you do then? That's where the vaguely violent
practice of shadow piercing comes into play. Shadow piercing is just that, a way to
bypass the encapsulation provided by shadow DOM either native or emulated in very
specific instances without making further reaching changes like changing your
encapsulation settings. We do this with a CSS pseudo-selector the Angular team added
called ::ng-deep. Largely, this was added by the Angular team as a bridge between
when the popular browsers stopped supporting other older methods of
shadow piercing and the new method of doing so, CSS variables. At this point, early
2018, CSS variables are supported by all current major browsers except IE11. But
there're some issues in the Angular CLI tooling that need to worked out, so CSS
variables aren't quite ready for primetime use in our Angular apps. The Angular team is
committed to keeping ::ng-deep around until it's no longer necessary. If you want to
read more about CSS variables,there's a good write-up on Mozilla. Using ::ng-deep is
easy. Just add the CSS pseudo-selector in front of any class you need to be able to
break the shadow DOM encapsulation. This method will eventually go away when the
tooling issues for CSS variables are worked out and IE11 is no longer a supported
browser. For now, though, it's what we have, so let's go take a quick look. Shadow
piercing gives me the ability to control the styling of elements on my page pretty
granularly. If I go in and look at mywidget, you can see I'm back to my colored blocks. I
have one colored block in my parent component that is orange. And then I've got five
other colored blocks each in a separate child component, and right now each of those
child component stylesheets make that colored block yellow. Well, we want to be able
to change the color of those yellow blocks without having to go into each stylesheet
and change it there. So what do we do? Well the first thing we're going to do is we're
going to go take outthe stylesheet's specific colors. So we'll take these out. Save
everything and jump back over to my browser. When I reload that widget, all those
child boxes should now be white. So they're unstyled. Now I want to be able to change
that style easily, so I'll go into the stylesheet for my parent component. This is the
widget itself. And I'm just going to uncomment this style right here, and you can see
I'm using the ::ng-deep pseudo-selector. If I go ahead and save this and jump back over
to my browser, when I reload that widget, the child ones are blue, the parent one is
still orange. So the ::ng-deep said starting at this level, pierce through the shadow
encapsulation of all of my children, not me,everything below me, and apply this rule to
those elements. So now when I need to change this, if I want to make them red, reload
my widget, and they're all red. So that's working with shadow piercing, the ability to
say in this specific situation, I want to be able to control the styling of elements from a
certain level. I want to be able to control the styling if it's children. Remember, it
doesn't apply to that level itself, it's everything below wherever you set the ::ng-deep.

Building Custom Pipes - Dynamic Display Manipulation

Earlier in the course, we discussed the usage of pipes to modify the display of content.
And we looked at the out-of-the-box pipes provided by Angular. Later in the course,
we're going to talk about pipe performance, but now we're going to focus on building
custom pipes to modify the data displayed in our UI. Angular ships with three pipes
that can change the casing of letters displayed in your UI--LowerCase, UpperCase, and
TitleCase. The name of each pretty well explains what it does. The use case we're going
to look at is from an application I wrote that I had a need similar to these, but for one
specific reason, none of them fit the bill. I needed the casing to be dynamic based upon
user preference. None of these gave me that option, so I had to build it myself. Let's go
take a look at this use case for building a custom pipe. From a custom pipe, remember,
I need to be able to control thepresentation or the casing of certain pieces of content
based on a value in a configuration object. So if I go ahead and load my widget for this,
you can see I have a button that's going to toggle through the different available
values, and then I just have a string that gets presented. As I click the button, it
changes that configuration setting, and you can see that the presentation changes. So
the pipe is updating its content based on that configuration setting. Looking at the
code, here's my HTML. I just have my string, and I'm piping it through my dynamicCase,
and I pass in the configuration setting. So that's going to come in as the arguments to
the pipe. Configuration is just---or cfg is just an object that controls or that stores my
configuration values. The pipe itself implements the PipeTransform interface.It has the
transform method. It gets a value, which is whatever piece of content the pipe is being
applied to. In this case, it's going to be a string. And it takes in the arguments. And
that's where I'm passing in the current configuration setting value. In my code, all I'm
doing is depending on what the value of args is, I manipulate the value string to either
UpperCase, LowerCase, or TitleCase. So toTitleCase is just I lifted this right out of the
existing toTitleCase pipe that comes with Angular, but I added it to my custom pipe,
which allows me to control based on that external value. The button that I click calls
this changeCase, and all that's doing is changing the value of my configuration setting
object. So it's saying if you're already AllCaps, we're going to change you to AllLower or
Title or whatever the default is or back to AllCaps, so using a pipe to do what typical
pipes do or what the out-of-the-box pipes do, but adding a little wrinkle in that I'm
controlling that value externally. So now if the users come in and change their
configuration settings, the presentation of the content will be updated
appropriately, and there's nothing I need to do about it.

Directive Selectors - More Than Just Attributes

We've all seen directive selectors, and earlier in the course, we looked at a pretty
vanilla example of a selector for a directive, a standard attribute that applied the
directive's functionality to whatever element it was applied to. But there are other
selectors we can use as well to get either granular or broad, depending on how
we need our directive applied. All of these present some pretty interesting ways to
modify our UI. So let's list them out here and then go take a look in our demo. First, a
selector for an element. Here our directive will be applied to every anchor tag. A
selector using a CSS class. Our directive will be applied to any element with that class.
A slightly more complex class selector hereusing not to control where the directive is
applied a little more granularly. Multiple classes, filtering the elements to which the
directive will be applied via an attribute. And like multiple classes, applying the
directive via multiple selectors, but this time combining different selector
types. Working with directives, I'm assuming that everybody's familiar with what are
called attribute selectors, which is when you actually take the selector for your
directive and add it as an attribute onto an element. That's the typical usage. But we
will look at some other selectors. So we've just some text on the page. You can see
mostly I'm changing color based on some criteria that we'll take a look at when we
get into the directives. So I have a stylesheet that just applies some of the colors. In my
HTML, you can see this is what delivers that unordered list on the browser page. I have
a simple anchor tag. I have a span with an attribute selector of qualified. I have another
span that does not have that attribute selector, so it's not qualified. And then I just
have a bunch of spans that have different CSS classes, so class, class1, class1 and
class2, class3, and then last I have a span that has another attribute selector just called
hsPaywall.Looking at the selector directives TypeScript file, now I have these all in one
file just for simplicity's sake. Typically I would break them out. But I wanted to be able
to get through them fairly quickly with you. So we started with a selector that is just
anything with the CSS class of class. That's going to be changed to blue. Now in the
constructor, you see I'm injecting an ElementRef. This gives me a reference to
the whatever item my directive is applied to. So in this case, it's anything that has this
class on it. I'm also injecting a Renderer2. Now Renderer2 is something we're going to
take a look at a little bit later in the course. But for now, just understand that
Renderer2 and nativeElement used properly are how you're supposed to manipulate
the UI inside Angular. So scrolling down, we have a slightly more complex selector,
which is saying anything that has class1 but not class2 is going to be green. Here we're
applying multiple selectors, and we're using selectors of different types, so we're using
a class selector, anything with class3, or that has the hsPaywall attribute selector. So
anything that has one of those is going to be colored orange. Now here's an interesting
one. We're saying apply this to all of the anchor tags anywhere on my page. We come
down here, and we're going to add this class to it, classFromDirective. Now the
interesting thing about this is it said it's anywhere on my page.I don't actually have to
add this directive anywhere. Simply having it in a module that's been imported in the
current set of components is going to go and touch every anchor tag. So be aware of
that because that may give you much broader reach than you expect. It can also make
things a little bit harder to troubleshoot because there's nothing explicitly on the page
that says, for example, this as an anchor tag is going to be updated, the presentation's
going to be updated in some way. The directive applies to all anchor tags whenever
this module is imported. Scrolling down, we have here our span with the attribute
selector of qualified. So that says that it's going to apply to this span but not to thisone
because this second one doesn't have the attribute selector qualified, so it wouldn't
apply there. And if I had something else on my page, like if I went in and changed,
added the selector here, it would not apply there because it's not a span, it's an anchor
tag. So I'm qualifying this to say only spans that have that attribute selector are going
to get this class2FromDirective class added to them. So that shows us some different
ways that we can use selectors besides just a simple attribute selector. Like I said, in
some cases, when you're selecting off of an element, you don't even have to do
anything. It's going to apply to all instances of that element. So using this to our
advantage really gives us some power for manipulating the way directives apply to the
content on our pages.

Host Binding - Manipulating a Parent from a Child

Once you know what host binding is, the name makes perfect sense. So what is host
binding? It's simply connecting a property on your directive to something in its parent
component. You can connect the directive to any of the following on
whatever component is hosting it in your component tree--a class, a specific style
element, an attribute, or a property. Usually having one part of your application
modify another is peer-to-peer or parent-child. Host binding gives us the ability to add
child to parent to that and have a parent change its presentation based on the children
it contains.Really quickly before we go to our demo to explore host binding a little
further, if you're uncertain of what I mean by a host, here's a quick definition. The host
of a directive is the element to which it's applied. So here the host of myDirective is the
div that contains it. Let's go take a look at host binding in our demo. Taking a look at
different examples of host binding, we have a couple of different examples on the page
here. We'll go through them one at a time starting with binding to a CSS style
property. You can see when I reload this widget, the style property we're changing the
color every half a second or so. Taking a look at the code, here's the HTML for my
component, In this first one where I'm binding to a style property, I'm using a directive
here called hsRandomColor. HsRandomColor, basic directive, but here's where I'm
binding to a property on my host. And in this case, the host is whatever element is
hosting this directive. So it's going to be this particular div. I'm specifically binding
to the color property. I start out as red, but in my AfterViewInit, every half a second I
pick a different color, generate a random color string, and change that color property,
which is going to update the value in the host. So that's what causes this to change
color. We can also bind to CSS classes. Here I'm going ahead and toggling a class, but
you'll notice every time I click the button, it doesn't change. That's because in my
directive, I'm applying some additional logic. Taking a look at that, here's where we're
binding to the class. Here's my directive, and I'm passing in a value of just a simple
Boolean. Now the button when I call this toggleActive, that just toggles the Boolean
from true to false. But in my CheckActiveDirective, here's my selector. Not only am I
binding to the isActive class saying if this is true, then I'm going to apply the isActive
class, I'm also accepting it as an input. So I'm taking it in from my host and
manipulating it in my directive. Here you can see why it doesn't always get applied
because inside my directive, I'm essentially saying just apply it 50% of the time. So I'm
just generating some random numbers to control whether or not I actually change the
presentation based on what comes in from my host. So it's a HostBinding to apply a
class. If the property is true, the property setter determines that it only happens 50%
of the time. But like I said, I'm also accepting this as an input from my host. So that
gives me the ability to pass in a starting value to this particular directive.So a slightly
different twist on the typical host binding. Next down we have---we're binding to an
attribute. This is an input here, a password input, just a regular password box. But if I
take a look at the dev tools, you can see that this has a minlength of 15. If I jump over
to my HTML, you can see here I'mspecifying a minlength of 10. But I have a directive
where the selector is input of type password, and it's going to use HostBinding to
change that minlength and force it to be 15. Now like we saw in some earlier demos,
this is going to apply to every input of type password anywhere where the module
containing this directive is available or is imported. So it's going to force essentially a
global default anywhere this module is used so that passwords have to be 15
characters long. And there's really no way to override that. Last but not least, we have
a binding to a property, in this case the value, and you can see this has a value of set
from Directive! Looking at the HTML, I just have an input with an attribute selector for
my directive. The ValProp directive binds to the value property of my input, starts with
an initial value of initial value, but then has a timeout so that after 5 seconds, it
changes that text.So that's a couple of different examples of binding to different things
in my host--classes, CSS styles, attributes, and properties.

Host Listening - Responding to a Parent From a Child

As you would expect, host listener is similar to host binding. However, instead of


binding to properties of the host, a host listener allows us to respond to events raised
by the host or even further up the hierarchy. While this isn't exclusively restricted to
just modifying the UI, that's often the case for our response to an event. So let's take a
look at this in our demo as well. In the host listener demo, I have two different host
listeners set up. You can see when I click anywhere in my document down in the
console, we get an event logged. Just click via document and then the
actual information about the event. So that happens every time I click anywhere inside
my document. If I clear that and then I go and click inside this little black box here, I'm
going to get click via Directive. Document, Directive, document, Directive. Let's take a
look at the code for those two different listeners. Here's my HTML for my
component. Let's see, I have a div. That's my black div on the page. I'm putting a
directive on it with an attribute selector of hsClickListener. We'll take a look at this, but
I'm binding to an input property and passing in a handleClick. That's a function. When
we go into the TypeScript for that, you can see I have one HostListener registered. This
is how you register a HostListener, and this is the one for the document. So I'm passing
in that I want to listen to the document:click event. And when that happens, I'm going
to take this parameter and pass it in to this function. So this is where we get logged
click via document, and I get that MouseEvent object written out into the console. So
that is one way of registering a HostListener where you come in and you explicitly say,
This is what I want to listen to. If I wanted to change this to listen to just clicks on my
element, I would do that. I would take out the qualifier. Now I'm going to listen to
clicks just on that black box. The other listener that I have is registered a little bit
differently. I have a function here. This is my handleClick. And you can see this is what
logs out to the console. And this is what cancels so we don't see the document click
because I canceled the bubble. And that's this here. HandleClick is the function, it gets
passed into an input property on my directive. So the directive itself is a pretty
straightforward directive. It's going to register an input. It's a function that's going to
take a MouseEvent as a parameter, and that's how I pass in the function from my
TypeScript file on my widget and say when the click event happens on whatever the
host of this object is, which in this case is this div, my black box, I want you to call this
function, pass in the parameter. If we have a listener, then we're going to call that and
pass in the event that we were given. So that comes back and calls my
handleClick here, which is what actually writes things out to the console. So that's a
slightly different approach to writing a generic directive that's going to take in a
function and do the registration of the HostListener for, in this case, a click event.You
can see the registration is the same regardless of how I'm doing it. But the directive
gives me just a little twist on the way things work.

NativeElement and Renderer2 are NOT Bad

NativeElement is somewhat contentious in the Angular world, but at its core, it's pretty
basic and uncontroversial. When developing for a browser client, nativeElement is
simply a DOM node, an HTML element somewhere in the DOM. In the picture on the
screen there, each div and paragraph element isa DOM node and so can be
represented by nativeElement. My caveat of when developing for a browser client is
important, and it hints at the controversy swirling around nativeElement and its
use.The above holds true when developing for a browser client. The same does not
hold true if developing for some other client or for an environment that doesn't
understand DOM nodes in the sense that abrowser does, namely for server-side
rendering or web workers. And that gets us to the heart of the important stuff you
need to know about nativeElement. It's there, it's available, it should be used, but only
in certain ways and for certain things. That's what we're going to cover in the next few
minutes, how and when to use nativeElement. This is what the Angular team has to say
about using nativeElement. It's a big caution call out on the ElementRef documentation
page warning you of the dangers of this element. In order to understand why there are
rules around using nativeElement, you need to understand the potential problems it
creates when used improperly. These were alluded to in the warning from the Angular
team on the last page, but let's call them out here. First, it tightly couples your back-
end code to your front-end presentation. Second, it's unavailable in Universal, which
means among other things no server-side rendering. And, third, you can't move any
logic directly using nativeElement into a web worker. You knew there had to be a but.
There always is. All of these are surmountable problems if you use nativeElement
properly. So let's look at what that means.

Getting and Using NativeElement Properly

First, we'll look at how to get nativeElement. NativeElement is a property of


ElementRef, so anything that gives us an ElementRef is going to give us access to its
nativeElement. Some of the way we've already seen include one of our query
decorators directly to an element via a template reference variable, one of our query
decorators using a type as the selector but reading the ElementRef token, injecting it
via the constructor as seen here for a directive. There are other ways, but you get the
idea.Once we have the ElementRef, we can begin to work with nativeElement. Now
that we have an ElementRef, let's start to use it. First some examples of what you don't
what it to do. Each of these directly accesses a property or method on
the nativeElement object, and this is what the Angular team is warning us
against. There are really two ways that you can safely disregard the warnings about
accessing nativeElement. The first is when you know beyond a shadow of a doubt that
you'll never, ever use Angular Universal, never attempt any type of server-side
rendering or pre-rendering oranything like that, and will never, ever move your code
into web workers. In those cases, there's no reason not to use nativeElement
directly. Again with the but. Yes, you could do this, but none of us can see the future,
and we'd be lying if we said that project requirements never, ever changed. If you
want to make that call, though, I'm not going to stop you. Just know what you're
getting into. You should know, though, that the other option is really pretty painless, so
you really ought to go that route. I'm talking about the Renderer2 class in
Angular. Looking at the members of Renderer2, you can see it does just
about everything you want to do when you think you need direct DOM
access-- creating and destroying elements and nodes, appending and
inserting, working with attributes, adding and removing classes and styles, setting
values, and adding event listeners. The difference is that Renderer2 does this all in an
environment-safe manner, meaning that if you're using it in Universal or in a
web worker, things won't break. Looking at the previous code, this means that instead
of the firstexample, we do this. Instead of the second, this. Instead of the third, we do
this. And instead of the fourth, this. You can see none of the Renderer2 code snippets
are particularly onerous. Other than having to pass in the nativeElement to work
against, they're practically identical to their plain vanilla JavaScript
counterparts, except that now we're not fighting against Angular. We're doing things
the Angular way, which means we're writing better Angular code, and people on Stack
Overflow won't mock you. Let's go take a look at a demo using nativeElement. We're
going to take a look at some basic uses of working with nativeElement and Renderer2
in this demo just kind of as an introduction.And we'll dig into it in much more detail in
the next demo where we start to look at using Renderer2 and nativeElement instead of
jQuery. So we're going to select our widget. It just gives us two buttons--Add Link and
Select Root Element. Starting with Add Link, it does exactly what you think it would do,
it adds a link onto the page. If the link works, it just pops up an alert box. Taking a look
at the code for that, here is my HTML, just two simple buttons we call addLink
or selectRootElement in my code. In order to work with Renderer2, we need to inject it
first. So in our constructor, we inject Renderer2, use a variable called ren. And here's
my addLink function. We're going to use different functions on the Renderer2 object in
order to interact with the DOM. So the first thing we do is we create our anchor tag
using createElement. We set properties, the href. We then create a text element. We
append the text element onto the link with appendChild. We go and get the parent of
whatever node caused this event to fire, so in this case, it's our button. We go get the
parent node of that with ren.parentNode. Now one of the things that you'll notice
as we're working with Renderer2, typically when you're working with the DOM, you're
going to need to pass in the element that you want to work with. So we're saying go
get the parentNode, and here's where we want you to start from, the target of this
function. Then we call Renderer2 again, and we call appendChild. We say I want you to
append onto my parent node the link that I just created. And that's what gets us just
the anchor tag showing up inside our HTML, inside the DOM. Now the other option
here is Select Root Element. And this one's a little bit odd. I want to show it to you
because I don't think it does what a lot of people would expect it to do. I know it
confuses me a little bit. So when I go and select the root element, it looks like my
button went away. If I open up my browser tools (give us a little more room here), you
can see that what happened was just that everything inside that button got cleared
out. So let me load this up again and show you if I go and select this button, you can
see that it has the text Select Root Element. When I go and click it, that text goes
away. So that's a little bit of a quirk about what's going on here.Taking a look at the
code, all we're doing is saying use Renderer2, saying selectRootElement and passing in
our target again. So in this case, the button. And the quirk about selectRootElement is
that it will go and get that element, but it clears out its innards. It takes everything
that's inside of it and gets rid of it. And this is what I think is a little bit not what people
expect. I know it's not what I would expect. And I've yet to see anybody come up with
a real good explanation as to why it does that. So just be aware that you can go and
get really any element on your page, but it's going to clear it out. So that's probably not
what you're looking for. Again, this was a pretty basic introduction of just getting and
working with Renderer2. We're going to go into this in a lot more detail in the next
part of the course and the next demo. So let's get back to that.

JQuery as an Angular Anti-pattern

Does jQuery belong in your Angular project? I'm content that the answer is No, but
let's take a look at how I arrived at this decision so you can make up your own mind. In
order to answer this question, we need to take a look at what jQuery gets us. First, the
biggie, DOM manipulation. As we've seen throughout this module, Angular has that
covered. Anything jQuery can do in the DOM, Angular can do. After all, jQuery is just
JavaScript sugar. But JavaScript and the browsers have mostly caught up to the
point that we really don't need that sugar anymore. Next, event management. We
haven't looked at it specifically in this course, but Angular has that covered as
well. AJAX? Angular has that too. Async? Promises and observables both covered when
you include RxJS. Animation? Check. And that leaves plugins. jQuery has a rich plugin
ecosystem, whereas Angular doesn't. But there are several open-source
component libraries for Angular that provide a lot of what the jQuery plugins offer. I'm
not sure that any jQuery plugins are worth importing jQuery into your Angular project.
Certainly you can, and people do, but this is not the Angular way and introduces all the
problems this module hasshown us how to overcome. I'm not saying that jQuery is
bad. It almost single-handedly catapulted JavaScript development from a lightweight
also-ran to the juggernaut it is today. In its heyday, it was the technology to know. But
now the world has changed. This is what I'm saying. In all the important ways, jQuery
and Angular cover the same ground. And then Angular goes on much further. If you've
decided that Angular is the right technology for a given need, then you really also
decided that jQuery is not. Don't try to jam it in. I'll stop pontificating now, but just
realize that you really need to pick one, whichever you decide is the best for the task at
hand, and run with it. Whatever you do, don't pick one just because it's what you know
or because it's the shiny new object in the dev world. Make a conscientious choice for
a given need, and you're going to be okay. Now as I said in the slides, jQuery is not a
bad library. But it really doesn't belong in an Angular project. We need to have some
way of doing the things that jQuery lets us do. So let's see how we accomplish that in
Angular. So we've got a couple of different scenarios we're going to take a look
at. We'll take a look at showing and hiding elements, adding and removing content,
adding and removing classes, adding and removing attributes, adding and removing
styles, and registering and unregistering listeners. And those are typically the things
that we use jQuery for. So let's see how we would accomplish those without jQuery,
just straight Angular. Showing and hiding content--we can actually show it or hide it, or
we could use ngIf to add it and remove it from the DOM. We talk about DOM
cleanliness a little bit later in the course. But either of these are options for showing
and hiding content. Taking a look at our code, a couple of things to knock out of the
way. The stylesheet just has a couple of supporting styles that we will make use of. The
HTML itself--here's our first scenario showing and hiding. We've got two buttons that
both call flipUI. We have our ngIf working off of an inDom Boolean. And then we have
the hidden attribute bound to a hidden variable. Calling flipUI just switches those
toggles back and forth. So those are two different ways to add and remove
content, make it visible or not visible in the UI, but we're not really touching the DOM.
We are, Angular is for us. We're just writing JavaScript that updates variables.Next,
adding and removing content. So I can click the button and have my content show up
or disappear, depending on how I have things toggled. Again looking at my HTML, this
time I'm using binding. So I'm binding to the innerHtml of my div. What I'm binding
there is a variable called boundContent. Over here, I set up boundContent to this
value. And then when I click that button, I'm just changing based on
this contentVisible, I'm changing the boundContent value to either an empty string or
my displayed string. So, again, in these two examples, I'm really not directly
manipulating the DOM. I'm changing JavaScript variables in my JavaScript code, and
Angular is updating the DOM appropriately. In the next case, we start to touch the
DOM a little bit more directly, so we're adding and removing a class. A class either
highlights or unhighlights my div. In my HTML, here's my button. It's calling this
toggleClass. And you'll notice now for the first time I have a template
reference variable on my div. We're going to make use of that inside the code. So let's
go take a look at toggleClass. ToggleClass is going to work with a private variable I have
set up called classElem. Well what is that? Up here inside AfterViewInit, I make a call to
this initElements. What that's going to do is take all of the ViewChild properties that I
have up top here and grab their nativeElements. Now you read a bunch of things on
line that talk about how you really shouldn't work with nativeElement, which is a little
bit misleading because it's not so much that you should work with them, just that you
shouldn't directly access their properties. But there is a way to safely work with
nativeElement. So let's go take a look at how we do that. So we have all these different
ViewChild decorated properties that give us an ElementRef. We go down to
initElements, and we're going and saying if we have a class, which is one of our
properties, and it has a nativeElement, then we're going to set a class element to be
that nativeElement. Same this for the attribute, the style, and the listener. So those are
all of our children that we specified up here, all the ViewChild properties. So now we
have classElem representing the div. We have a Boolean that says, Is the class turned
on? If yes, then we're going to use the Renderer2 and remove it. Now Renderer2 was
passed in---where's our constructor go? Here we go. We passed Renderer2 or we
injected it in via our constructor. So we call removeClass. We're going to work against
the classElem property, which is our div. And we're going to remove the highlight
class. When we're toggling the other way, we use addClass and add highlight. Then we
just toggle our class variable either on or off. So that gives us the toggling of this class
to highlight or unhighlight. Similar for attribute. I have a button down here. When I
click on the Attribute button, this button gets disabled.Click it again, and it toggles to
enable. So the same type of thing. I have a nativeElement here, and I'm removing the
attribute disabled, or I'm setting the attribute disabled to a value of true. So that's how
you would work with attributes using Renderer2. Styling text--I'm changing the color of
it by clicking on the button. Similar approach, we have our nativeElement that we've
set up inside of styleElem, and we call either removeStyle or setStyle depending on the
value of our Boolean. When we're setting the style, we pass in the element that we
want to apply it to. In this case, it's our nativeElement that represents that style
div. Here's the style that we want to set and the value we want to set it
to.RemoveStyle we just pass in. To take out whatever value is in for color, just remove
it entirely. And, last, pretty typical thing to do with jQuery is register and de-register
listeners. So you can see my listener is on or off. When it's on, when I run my mouse
over my div, it changes colors. It just goes to a random color every time I move. I can
turn it off, and the color changing goes away. We saw doing this with HostListener
earlier. But here's a different way that we could register listeners. The first thing we're
going to look at is actually when listenerOn is false. That's when we set up our listener.
We're going to store the return value from the Renderer2 listen function in this
listenerFunc, which we declared up top here, right here. So we call ren.listen, and we
say here is the element in my DOM that I want to listen to. Here is the event that I
want to listen to. And what I want to do is call this listen function and pass in the event
parameter that I got from the browser. Listen down here is just adding a style where
it's just adding the background color. So that's my event handler. Now the interesting
thing is the return value from listen, from the ren.listen method, gets stored in this
listenerFunc. We now have a function registered as a listener. If we want to unregister
that or de-register that, we just call that return value, and it's going to de-register the
listener. So this is what essentially turns off my listener when I need to.Typically, you
would do something like this in an ngDestroy, but you could do it at whatever point
your requirements call for it to be done. So that shows working with Angular and just
plain JavaScript,specifically in a lot of cases working with the Renderer2, but
sometimes not really interacting with the DOM at all, like I said. In these first couple of
things, we were just working with JavaScript variables and letting Angular update the
DOM and update the view appropriately. But that's how you can do a lot of the things
that we typically in the past would have used jQuery for in an Angular
environment. And it keeps us separated. It keeps our DOM and our back-end
separate from our UI and the view that the user is interacting with.

Wrap Up

That brings us to the end of our discussion on manipulating the UI. We started with
simple view encapsulation and saw how changing it can affect the UI in different ways
just with simple CSS. We looked at building pipes and directives including a whole
range of directive selectors that can provide a whole lot of value. We covered host
binding and listening to allow children to modify their parents.And then we spent a fair
amount of time on the proper way to interact with DOM elements programmatically in
Angular using nativeElement and Renderer2. Finally, I jumped up on my soapbox for a
bit and discussed why jQuery, while a fine library in and of itself, really doesn't belong
in an Angular project. And then we saw how Angular can do everything jQuery
does. We'll still be manipulating the UI in other modules, but there the examples will
be focused more on other things as opposed to directly manipulating the UI. For
example, in the next section of the course, we're going to look at making our UIs
dynamic including creating and displaying components on the fly and various flavors of
content projection.

Creating a Dynamic UI

Introduction

In this module, we're going to take our understanding of the UI and how to work with
it and really start to do some neat stuff regarding creating dynamic user
interfaces. We're going to talk about content projection both built in and finally making
use of the ngTemplate, as well as some of the aspects ofquerying our UI, which we
introduced earlier. We'll also discuss component inheritance on our way to two
different means of dynamically creating components based on runtime requirements.

Using Built-in Content Projection

In a sense, content projection is like input properties, allowing you to pass information


from a parent component to a child component. There are three differences, though,
which make content projection appealing. The biggest is the fact that unlike input
properties which pass a value to a variable and then the receiving component decides
what to do with that value, content project is strictly for display.Projected content is
either displayed or not. That's pretty much it. Why is this appealing? Simply because
it's focused. If you need to show content determined in one component in a location
specified in another component, content projection is the easiest, fastest way to do
that. Next, content projection can project nested components. We'll see an example of
this in the demo in just a few moments. Last, content project injects the entire DOM
node specified in the source component into the child. This gives you the ability to
still control the presentation styles and functionality of the projected content from the
source component instead of having to make the receiving component figure out how
to style any content it receives and include any functionality inherent in that
content.Angular has some built-in content projection that we can use
declaratively. We'll use this to get an idea of what content projection is all about and
then look at it in code in a demo. To show this content projection, we have a snippet
from our app.component, from another component which is referenced
inside app.component, and finally a look at the HTML output after Angular does its
magic. Starting the HTML, you can see we have two delimiters--asterisks and hashes--
which wrap everything we're looking at. Those obviously come from the first and last
lines in app.component. Nothing surprising here. The remaining content then comes
from my.component. But perhaps not in the way you would expect. We get the first
line of content from inside my.component showing up in the output. Then we get the
content that was actually defined in app.component passing through the ng-content
tag in my.component and showing up in the output. And, last, we get the final line of
my.component. It's pretty easy to see in this simple example, but the important thing
to know is that any content defined inside a component's opening and closing tags will
show up inside the body of that component's output wherever you have the ng-
content tag. If you don't add the ng-content tag, content won't show up anywhere. If
you include more than one ng-content tag inside my.component, the last one listed
will be used to display the content. Any previous ones are ignored unless you make use
of a capabilitycalled multi-slot or named content projection. Named content projection
lets you define multiple pieces of content and then have multiple ng-content elements,
which are configured to display a specific piece of content. Each specific piece of
content can be identified by an attribute, a CSS selector, or via a component's element
tag. Let's go take a look at these plus normal or single-slot projection in our
demo. Loading up our content projection widget, I'll quickly go over what we have
going on on the screen here, and then we'll go back into Visual Studio Code and see
how we got there.So we have a title of Content Projection, and that's styled
larger font, it's black, and it's underscored. And then we have the text below that, the
content is styled green. Now all of that is controlled by the parent component, except
for we're doing a slight bit of trickery to get the title there, Content Projection, actually
styled in the child. So we have the title being projected, we have the green content
being projected, and then we have this other text down the bottom, which is also
being projected. But it's not into a specific named slot. So taking a look at Visual Studio
Code, here is our widget component. This is where we're specifying all of that
content. We have a content-projection-child element. All this is content within that
element. So we have some unnamed content. Then we have a div with a class of
content. And this is where that stuff in the middle came from. We then have another
block of unnamed content. It's just a paragraph. We have another block that has a no-
selector attribute applied to it. But this and this and this are all considered unnamed. If
we look back in the browser, they end up all down at the bottom here. The content
piece and the title specified down at the bottom here are named. The title has a
attribute of top, and the content it has a class assigned to it of content. Looking at the
CSS for our parent, you can see here's where we're specifying that our content is
green.When we go over to the child in the HTML, you can see we have our ng-content
that's saying I want to display a piece of projected content. Specifically, I'm going to
select the piece that has the topattribute on it. So that's this down here. So it's going to
put that div in this location in place of the ng-content. Now we're styling this in the
child because I have it wrapped inside a div with a class of title. And that's what's
specifying the styling for this. There is no styling in the parent component. If there
were, it would override this. Next up, I have another ng-content. Here I'm going for the
content, so anything that has a class of content. So that's going to be this piece. You
can see there's my title, and there's my content. And then I have an hr, a horizontal
rule, and then I have an unnamed ng-content or untargeted ng-content. So this is going
to pick up anything that doesn't have an identifier back here.So that's this and this and
this. And the unnamed pieces will be displayed in order. So that's these pieces down
here. And the last thing I want to show you is that in the stylesheet for the child, I am
actually attempting or I'm specifying a different color for my content, but it's not
applied because it's handled by the parent. We don't see blue text, we see green
text. And then you can see here's where I'm specifying the information for styling the
title. And that gets picked up because it's wrapped inside this, and inside the parent, I
don't specify any styling for that content. So that is named and unnamed content
projection. As I said, it gives us the ability to, without code, take content from the
parent and project it into the child and have the child control the location, but the
parent still controls the presentation, the styling.

Wrapping Content in ngContainer

NgContainer is a simple little thing but quite handy, especially in combination with


structural directives like ngIf and ngFor as a way to group DOM nodes without
introducing unnecessary nodes into your DOM. Looking at the code here, it probably
looks similar to something we've all written, a simple ngIf to conditionally display one
piece of text or another. Minus some comments from the ngIf that aren't relevant right
now, the resulting DOM looks like this. No big deal and probably exactly what you
would expect. Contrast that with this next block of code, notice that we're using ng-
container instead of span, but that the two code samples are, otherwise, identical.
However, the resulting DOM is now this. Notice that the ng-container isn't included in
the DOM, whereas above the span is. If you're thinking to yourself, That's it, that's all
ng-container does?, you're not far off the mark. It's not a huge deal, but it does have
some benefits. And knowing it's available means it's a tool in your tool belt which you
can use when you come across a need. We'll use ng-container frequently in the demos
throughout the course. The primary reasons for using ng-container are a cleaner
DOM, not just because you may be OCD about it, but it also makes the DOM ever so
slightly smaller, which is never a bad thing, and in myopinion, makes the DOM easier
to read if you need to debug, and anything that helps with debugging is a good thing in
my book. Avoiding potential problems with your CSS selectors if you use positionally
sensitive selectors such as nth child. The extra DOM nodes could present a
problem. Personally I find this use case a little weak, but I won't discount the possibility
of it being a problem. And, last, the potential for extra DOM nodes presenting
accessibility concerns, for example, for screen readers. We're not going to jump over
into my demo machine for ng-container because it's really this simple. The code I
showed two slides ago is all there is to it, and we'll see ng-container used in later
demos, so you'll see it multiple times.

Building Templates with ngTemplate

We discussed ng-template briefly earlier in the course. We're going to dig in deeper


now. Ng-template is used internally by Angular when it de-sugars some of the
structural directives like ngFor and ngIf, but we're going to talk about cases where
we're actually using ng-template in our HTML. Using ng-template is as easy as what
you see on the screen here. And this is what it renders to in the UI. No, this isn't a
mistake. The slide's empty just like the UI rendered by ng-template. By itself, ng-
template does not put any content into the user interface. We need to take some
other steps to make the content inside the ng-template show up. If you're curious,
here's what ng-template adds to the DOM, just an empty comment. In the next few
sections of the course, we'll see how we can use other aspects of Angular to
display the content from an ng-template where, when, and how we want.

ngIf-Else with ngTemplate

As we just discussed, ng-template by itself does not appear in the UI, and that's what's
important about it. We can define a chunk of UI and then decide where, when, and
how to display it. Let's take a look at a couple of scenarios for that. Angular v4
introduced the ability to add an else block on the standard ngIf. But using it requires
that you use ng-template. You can see the syntax here. We have our ngIf structural
directive with its condition. So far nothing different from a standard ngIf. But then we
tack on a semicolon, the word then, and a template reference followed by else, and
another template reference. Now we have a full conditional expression. If the arriving
condition evaluates truthy, Angular will show the arrivingContent template. Otherwise,
it will show the departingContent template.There're some other forms to the new ngIf
that could use an ng-template, so let's go take a look at them. So on the screen here,
we just have basically three very simple scenarios. We have an Inline If with no else
specified, and we'll take a look at these in the markup in just a moment. We have an
Inline If with an else. And then we have a Template If and a templated else. And you
can see as I toggle a simple Boolean variable true to false, the content is largely the
same. The takeaway from this in the UIis that the user doesn't know and doesn't care
how you ended up presenting this information. It's really a matter of code
preference in the background. Taking a look at that code, starting in the component
TypeScript file, like I said, we're just toggling a simple Boolean variable. The real fun is
in the HTML file. We have our three scenarios. We have an Inline If with no else, so if
our isEnabled is true, then we're going to show this enabled content, which as the
title says, it's specified right in with my ngIf. The one below that we have an Inline If,
and we have an else specified. Now the else has to be specified as a template. So we're
saying if it's enabled, it's going to display this inline content. Otherwise, else, it's going
to go down and get this disabled template, and that's specified at the bottom of the
page here.And it's going to display that. The third option is really combining everything
into templates, and we're just saying if it's enabled, then go and display the enabled
template. Otherwise, display the disabled template.

Rendering Content with ngTemplateOutlet

NgTemplateOutlet is used to inject a template into a specific location on your page.


Imagine we had these two templates in a component. They define a chunk of UI but
don't get shown anywhere until weexplicitly tell Angular where to display them in our
UI. One of the ways to do that is with ngTemplateOutlet. If we define a place for
templates to be injected using ng-container to avoid adding additional items into the
DOM and use ngTemplateOutlet to specify a template using the template reference
variable assigned to that template, Angular's going to grab that template and inject
it into our ng-container. If we change the template pointed to by
the ngTemplateOutlet, Angular will change the displayed template. There're only a few
situations where you hardcode the value forngTemplateOutlet like this. More often,
it's determined dynamically. Let's look at a use case for ngTemplateOutlet that
provides value and ultimately gets to the point where we're dynamically determining
which template to display. NgTemplateOutlet is going to be useful any time you need
toprogrammatically decide which chunks of your UI to show. This isn't quite
dynamically creating components, which we're going to look at later. Instead, consider
the ngSwitch replacement we lookedat earlier, as well as situations like displaying an
alternate UI for shared data, or displaying common repeated UI elements on the
screen, or dynamically determining where on screen elements are going to be
displayed. What each of these scenarios have in common is that we start with
a defined chunk of our page, a template, and use the ngTemplateOutlet to determine
if and where it appears on screen.We'll see an example of this in just a minute. But first
we're going to introduce one more part of
ngTemplateOutlet-- ngTemplateOutletContext.

Dynamic Content with ngTemplateOutletContext

Templates are great for stamping out multiple copies of content, but honestly how
often do we repeat the same exact content on a page? Sometimes, sure, but often you
need to vary it slightly. So you want to pass in variables into your template to
customize what it displays. This allows you to make some or all of the content dynamic
and determined in code if that's what you need but still have the template control the
display declaratively. We can do this by passing a context object into the
ngTemplateOutletdirective and then referencing it in our template using
interpolation. The real benefit to this is that it potentially avoids creating a lot of extra
components if you just need to alter some simple displayed data. Remember,
templates don't have an associated class, so there typically isn't any way to run some
code for a template. If you didn't know about ngTemplateOutletContext, you might
have otherwise created separate components for this, which a lot of time would be
overkill. Certainly this isn't going to be the right approach if you're changing large
amounts of the content, but for smaller, simpler content modifications, simply
switching up the context can be a nice approach. Let's go take a
look.NgTemplateOutletContext is going to work nicely when we have a template that
contains the structure that our content is going to be presented within, but the details
of that content might change fromone instantiation of the template to another. So the
TemplateOutletContext allows us to specify some details to get passed into the
template. So there're three different scenarios that I have on the screen here. We're
going to take them one at a time. We're going to start with No context. We've seen
this before, but I just wanted to call it out so you know kind of what the basics are. And
No context is just whatever's in the template gets put on the screen. There're no
dynamic aspects to it at all. Looking over in the code, we have our HTML page, and
here's where we have the ng-container, and it's going to go look for the noContext
template. Come down to my templates down at the bottom here, and here is my
noContext template. So you can see the content is hardcoded inside the template
itself, and whatever is in the template is what's going to get displayed up here in place
of this ng-container. And that's what we see on the screen here. In the second
scenario, we are specifying a context. It's fixed, and it's marginally more useful but still
now where we want to end up. Taking a look at that in our HTML, we're saying here's
my ng-container. We're going to use the fixedContext template, and the context
we're going to pass in we have specified right here inside the ng-container. So some
more value but not as much. You can see we come down here, our template is much
shorter. It just has a template reference variable of fixedContext, and then we have
our references into our context. We're saying let-contentType equal the contentType
from the context, and let-details equal details. So whatever is in the contentType
of the context is going to go here, and the details will go here. So when we come up
and take a look at the context, you can see we have our contentType, and here we
have our details. But, again, now it's hardcoded inside the container, not as useful as it
could be. Ultimately where we want to get to is a truly dynamic context. So here we
can have one piece of context that gets displayed when our condition is true, and this
could be retrieved from a server or doing some type of manipulation or content before
it gets passed into the context. But then we can have that conditionally change. So we
changed our condition, and the content down below changed. Taking a look at that
inside our markup, the Dynamic context, we again have our ng-container,
ngTemplateOutlet is now going against dynamicContext, and you'll notice that the
content of this template is the same as the one above it. Slightly different in the use
of our context variables, we now just say let-contentType instead of let-contentType
equals contentType. We'll talk about the $implicitin just a moment. And then we have
let-details equals details. The difference when we display this information is that we're
getting our context dynamically. It makes a call to get the context that goesout to this
function, getTemplateContext. That comes in and takes a look at our condition and
returns either context1 or context2. Context1 is defined right here. Now, again, this
could be coming from a server. I just have it hardcoded in here for the sake of
the demo, to make the demo self-contained. But you can see we have this
$implicit. You can think of that as the default. When you don't specify where to get a
particular context variable from like this, that's where you're going to get the $implicit.
You can only have one of those, one default. Everything else you need to specify which
property out of the context is that going to be pulling its value from. So we have the
$implicit, and we have our details.And then when we click the button, our condition
changes, and we switch over to using context2. It also uses the $implicit and has
different details. So this gives us the ability to have the same structure to our template,
but swap out some of the information, some of the details that get displayed within
that structure. And that's where the ngTemplateOutletContext on top of ng-
template really starts to provide some value in giving us the ability to dynamically
update our UI based on some programmatic conditions determined at runtime.

Component Inheritance

Up to this point in this module, things have been pretty vanilla. We've been using
mostly declarative, out-of-the-box approaches to introduce dynamic content only.
Now we're going to take things up anotch and start introducing dynamic functionality
along with dynamic content. We'll start with a quick discussion on component
inheritance and use that as a lead-in to creating components dynamically based on
runtime conditions. On the one hand, component inheritance is exactly what you
wouldexpect it to be--a child component inheriting things from a parent
component. But there are two things that you need to be aware of or that may
not work quite the way you expect. First, not everything is inherited by child
components. More specifically, the component metadata, the HTML template, and the
CSS styles are not inherited by the child component. With the caveat that you could
force the latter two to be shared if you wanted, I'll show you that in the demo. Second,
there's some dissension in the Angular community whether you should use
inheritance, instead preferring smaller more modular components which can be
composed, along with services and other constructs to build a master presentation
component without having to inherit anything. Personally, I think inheritance makes
sense for the reasons I'll explain as we go. If it works, doesn't produce unwanted side
effects,and is generally easier to build and maintain than other options, then I say run
with it. The most important thing is don't use component inheritance just because you
can. It can complicate the code a little bit and may confuse some new developers who
have never seen it before. Like just about all of the other guidance I'm going to give
you in this course, think about it. Use it if the benefits outweigh the drawbacks in your
specific project. At a high level, the scenarios where component inheritance make
sense fall into one or more of three buckets. You might have a child component that's
exactly like its parent in every way except the final presentation of the data. The
parent may present the data in a list and the child as a table for example. Another
possibility is that the presentation and data are the same, but the child needs to
run additional or different rules or logic. Finally, the presentation and logic may be the
same, but the original source data is different. Perhaps the parent displaying existing
customer data and the child displaying prospect customer data. Or both displaying
customer data but from different data sources. Certainly there are ways to
achieve each of these scenarios without component inheritance, and there's probably
nothing wrong with going that route. My take is if inheritance works and can help
reduce code duplication and complexity and generally make the application easier to
maintain, then we ought to at least consider it. Two, when combined withdynamic
component creation, which we'll talk about a little bit later, I think component
inheritance becomes much more compelling. We're going to take a look at a couple of
different scenarios for component inheritance. We'll bring up our widget, and we're
going to start just with our basecomponent presented on the screen. And you can see
it has a little bit of styling. Those asterisks that are on there are actually added in
code. So we'll take a look at all of that, but it defines a basic structure in our HTML. It
defines some base functionality in the JavaScript and base presentation in the
stylesheet. The children, when we take a look at those, are going to pick and choose
what they want to inherit. And we'll take a look at some of other aspects of inheritance
as well. So taking a look at our base component, nothing real fancy about it. I tried to
keep it simple while still being able to display the appropriate functionality and the
things that I wanted to get across to you. So, a couple of divs display the name, the
content, and then the footer information. The base stylesheet defines a couple of
styles. And the BaseComponent, we see not a whole lot special here. We're injecting a
service into the constructor. We set a property name to Base. We define some
content. We have a footer, but there's no content in the footer. And then making use
of some of the lifecycle hooks in our AfterViewInit, we're going to modify the text of
the footer if it has a value. We don't have that for the BaseComponent. There's no
value in footer, so it just gets skipped. And then here's where I said we put the asterisk
around the name property. We do that programmatically in the ngOnInit. So, again,
this is our base functionality. If I jump over and go into my widget, I'm going to
uncomment the first of the inherited children. Save that, let things rebuild. Jump back
over to our browser. We now see the first inherited child. We have a different class
that extends the base. This one makes use of the base component stylesheet plus its
own stylesheet, but it uses the HTML file from the base component intact. So we
specified some custom content in the class, and that's this text that's on the screen as
the body of this piece. We're making use of the base stylesheet, as well as a
custom stylesheet for this child to present the styling information. And then we handle
our event slightly differently as well. The ngOnInit event is going to be raised in the
child, but we don't call the parent or the super-class function. So we don't bubble that
up. We do, however, set custom content in our class for the footer, and the
AfterViewInit, we'll see it's not specified in the child, but the event in the parent still
runs, and that's what modifies the footer. So let's go take a look at the code for
this. Starting with our TypeScript file, you can see we have
an InheritedChild1Component extends BaseComponent. We specify a footer, and then
we specify the ngOnInit where we set the name property and the content property.
But we never make a call upto the base class, ngOnInit, which is why in this
presentation, we don't have the asterisks around the name of the component. You
notice that we don't have the AfterViewInit defined down here in the child, but the
one in the parent is still called, and that's where this text gets added into the
footer. And we see that right here. We're also specifying some additional information
in our stylesheet. You can see that we're overriding the header. In the parent, the
header is blue. In the child, we change it to green.So when we get down here in the
presentation of the child, it's green. So this first child is using the same HTML and
inherited TypeScript class, the same stylesheet, plus its own stylesheet. Next, we're
going to look at one a little bit different in Child2. So now when we go and load with
Child2 in place, you can see that we have our base class InheritedChild1, and we have
InheritedChild2, but it looks completely different. It's using its own HTML, so it lays out
its own structure. It's using its own CSS and not using the parent. So the presentation is
different. And it has its own functionality in the TypeScript.Now our TypeScript class is
still going to inherit from that base class, so we get some basic functionality. But in this
case, we do call, from the ngOnInit, we do call into the parent's ngOnInit. So we get the
asterisks around the name. Same thing we saw in the Child1 where we don't handle
AfterViewInit, but you can see down at the bottom here in the footer it's still handled
in the parent. We also have in our HTML, there is some hardcoded content. And then
the last thing that I want to point is that the inherited children have access to the
services injected into their parent. So you can see we have here this is a property from
the service. When we jump over and look at our code, if I looked at the class file for
InheritedChild2, you can see that it doesn't have a constructor. It's not receiving that
service. It's getting it from the parent. Here's our paragraph that's hardcoded in the
HTML. Here is where we reference the service that we retrieve from our parent. The
service just has that property that says this is a property defined in the service. So
we're using bits and pieces from our parent depending on what our desired
functionality is. So you can see how this can be useful for, like any other type
of inheritance, rolling information as high into the tree as you possibly can to provide a
common set of functionality or a common presentation or a common structure for
different components.

Dynamic Component Creation

Dynamically determining what UI and functionality is needed and creating the


constructs programmatically at runtime is the ultimate in dynamic UIs. Once we've got
these in our toolkit and learned where and how to use it, we're about ready for
whatever UI requirements are thrown at us. One thing to know about
dynamic components before we really dig in is that it's different from lazy loading. Lazy
loading is pulling statically created modules into your application as they're needed.
While some lazy loaded modules might contain dynamic components, not all lazy
loaded modules contain dynamic components, and not all dynamic components are
lazy loaded. Dynamic components are all about creating new instances of
previously defined components and injecting them into your application at runtime
based presumably upon values and conditions that can only be known at runtime.
We'll look at an example of this in our demo in just a moment. But, first, I want to
cover the pieces of Angular that make this all work. Be aware that this is one area of
Angular that's seen many changes from the beta through to the current release v5, so
while there's a fair amount of information on how to do this online, be careful because
a lot of it is outdated. This seems to be fairly well solidified now, so I don't expect it
to change much in future releases. There are two approaches to creating dynamic
components. The first uses a directive new in v4 called ngComponentOutlet. This
approach is mostly declarative. The only code you write is to actually assign the
component to be instantiated. That makes it pretty easy to work with at least for
simple scenarios. The other option is using ComponentFactoryResolver. Beneath the
covers, ngComponentOutlet is just a layer on top ofComponentFactoryResolver that
does the work for you. ComponentFactoryResolver is a programmatic solution, so it's a
bit more involved, but the code is mostly boilerplate, so it's not hard.The nice thing
about the second approach is that you get access to the dynamically created
component instance, so if you need to interact with its properties or events, you
can. For ngComponentOutlet, there's a pull request pending as of December of 2017
that will give access to the component instance inputs and outputs, which isn't exactly
the same as full access to the component instance, but it's a good start.

Overview of the Widget Framework

We actually see dynamically created components in just about every demo in this


course. But now we're going to go in and explicitly explore how we're creating each of
these pieces. The dynamically created components are the widgets that we've seen in
all of the demos. You can see I can load different widgets up to different areas of the
screen. I call them zones. So I have different widget zones, and I can select which
component I want to instantiate inside that zone. The code creates an instance of that
component and presents it on the screen. We're actually going to take a look at two
different ways to go about this. So over the next demo and the following two, we're
going to exploredynamically creating components. This piece first is going to
explore some of the framework pieces and some of the supporting elements. The next
demo we're going to take a look at the more programmatic approach of creating
components using the ComponentFactoryResolver. And then in the final demo, we're
going to take a look at the more declarative approach using ngComponentOutlet.But
let's start with some of the supporting elements over in code. So the widget
framework, all the code for this is inside the widget-fx folder. We have a widget-zone
for the ComponentFactoryResolver. Then we have a separate widget-zone for the
ngComponentOutlet. So we'll take a look at those in the next two demos. We have a
folder where all the widgets go. We'll take a look at those in just a second.We have
some enumeration utilities. We're going to use this really only in the
ngComponentOutlet, so we'll take a look at that. We have an interface, an IWidget
interface. All it does is say that anything that implements this interface needs to have a
widgetTitle property. So when I come in and take a look atmy widgets, let's pick
content-projection, go in and take a look at the widget, it's going to have a widgetTitle
property because it implements the IWidget interface. And that interface allows me
totreat all widgets generically. They're all an instance of something that implements
that interface. Coming down, we have our Angular module, and the only thing that's
really different here is that inaddition to declaring the components, anything that's
going to be created dynamically you need to specify as an entryComponent. Other
than that, there's really nothing different inside the module.Continuing down, we have
a couple of different widget-infos, one for the ngComponentOutlet and one for the
ComponentFactoryResolver. We'll take a look at those. We have an enumeration of
widget-types. That's only used in the ngComponentOutlet. So we'll take a look at that
then. And the widgetFx-config is only used in the ComponentFactoryResolver. So that's
kind of the underlying structure and an overview of what the widget framework looks
like. In the next two demos, we're going to take a look at the two different approaches
for dynamically creating widgets or components inside this framework.

Creating Dynamic Components Declaratively with ngComponentOutlet

I'm going to show you where we're switching between the two different scenarios, so
if you want to switch it back and forth, you go to app.component.html, and you can
see I just have a commented out block. This is what we're going to take a look at in the
next demo. This is ngComponentOutlet. The one we're using first is the
ComponentFactoryResolver. They're largely the same, but we'll take a look at some of
the differences when we get into the second demo. For the most part, we're setting up
the structure and defining this widget-zone, or in this case, two widget-zones on the
page. So that is how you would switch back and forth between the two if you wanted
to explore them. Moving down into our widget framework, here is the widget-zone.
We have a separate one for the ngComponentOutlet.We're going to focus on this first
one here. The HTML, nothing real special here, laying out some structure. I am using
Angular material for my drop-down menu. The really important part of this is this ng-
container right in the middle here, and you can see I have a template reference
variable on it called vc because we're going to be using that as our view container. This
is where we're going to inject our dynamically created components. Nothing real
special in the rest of this, so let's jump over to the TypeScript file and take a look at
what we have going on there. Here is our ViewChild, and you can see I'm explicitly
saying I want the ViewContainerRef. We come down. Inside our constructor, we're
going to inject an instance of our Injector and also an instance of the
ComponentFactoryResolver. The real heart of this functionality is inside this next
function here, ChangeWidgetType. That's what gets called when you select a new
widget out of that drop-down menu. It calls this ChangeWidgetType and passes in an
instance of this WidgetInfo. So WidgetInfo is just a simple class that has a
displayName,an internalName, and then also a property that represents something of
type IWidget. So that's going to be our actual widget itself. They all implement the
IWidget interface. So that gets passed intoChangeWidgetType. We have some
defensive code to make sure that we actually have a valid widget. And then we go and
get an instance of a factory. We make a call into the ComponentFactoryResolver,call
the resolveComponentFactory method, and we pass in the type of widget that we
want to create or the widget that we want to create out of that new type parameter.
From that factory, we get a componentRef. Using the injector that was passed in in the
constructor, this is where we're actually getting our newly created
component. Specifically, we get a componentRef pointing to it. Using our view
container, we go and clear any of the existing widgets out, and then we insert the
hostView of our newly created component. That effectively puts our component into
the UI. Now this next line is why I like using this approach as opposed to the more
declarative approach. For now at least, the only way that you're going to be able to get
access to the actual created component is to go this approach. You can call
componentRef.instance, and that gives you the dynamically created component
back. If you're going the declarative approach, you can't quite get there yet. So I store
that in activeWidget. I set up a property that gets displayed as the title of the widget,
and I'm done. That's what it takes to go and create using ComponentFactoryResolver a
dynamically created component and inject it into your page. Taking a look at the last
file that's involved here is this widgetFx-config. This is only used for doing things the
programmatic approach using ComponentFactoryResolver. And all this is, really this is
just geared towards setting up the menu for the choices. So I set my supported
widgets. I give them a name, a displayName, and then I actually give the type of
widget. That's what gets passed back here. So I get an instance of that WidgetInfo
passed back. And that's all configured inside this widgetFx.config. Next up, we're going
to take a look at doing it declaratively.

Creating Dynamic Components Programmatically with ComponentFactoryResolver

Now let's take a look at the approach for creating dynamic components that is more
declarative than programmatic. This is going to make use of the ngComponentOutlet
directive. So you can see I've switched. We're using a different version of the widget
framework. Functionally, it's exactly the same. I added the text at the top of the page
here just so you would know which version you're in. How we get there, though, is
slightly different. First, in our app.component.html, you can see I've switched to
usingthe bottom block of markup. And the only difference between these two is that
I'm using this widget-zone-co as opposed to just widget-zone. So let's go take a look at
the widget-zone-co. The HTML here is largely identical to what we saw in the last
demo. The heart of this again is the ng-container right here in the middle. The
difference is you'll notice that this doesn't have a template ref variable, and it does
have this *ngComponentOutlet directive using activeWidget as its value, so bound to
the activeWidget property of my widget-zone-co component. Starting at the top here
working our way down, we can see here is my activeWidget of type IWidget. Then,
again, the heart of this component is the ChangeWidgetType. So notice this one
compared to what we saw in the last demo, this one is significantly shorter. Really
that's just because I moved a lot of the work out into a separate function.So we're
changing the value of the activeWidget by calling getWidgetType and passing in the
newType. Again, that's WidgetInfo, slightly different from what we had seen before. It
just has the displayName and the Type. It doesn't have the internalName property. So
we get passed in from the UI.When you make a selection in the drop-down menu, it
passes in and instance of WidgetInfo. We pass that over to getWidgetType, which is
right down here at the bottom. And that's going through anditerating through an
enumeration that we have for all of the different WidgetTypes. That is right here. So if
we're using the ngComponentOutlet, I need some way to get this list, and I just have
them in a simple enumeration. So we go through there, and what I'm going to return
based on the value that's passed in is something that implements that IWidget
interface. So that gives me back this in the activeWidget property, which is hooked up
to this ngComponentOutlet. Behind the scenes, Angular is using the
ComponentFactoryResolver for us, but we don't actually have to go through and write
the code to create it. We have a more declarative approach, and I say declarative. It's
not purely declarative. There is still some code that we need to write. But you'll notice
that we're not actually working through the code to create an instance of that
component, we're just telling Angular the type of component that we want to have
created for us. A couple of other supporting pieces here, because I don't have access to
the actual instance that was created, I can't go and get its WidgetTitle directly, so I
have to pull that out of the WidgetInfo. So that takes care of the second approach to
dynamically creating components, slightly less functional than the first but less code
that we need to write as well.

Keeping Your DOM Clean

Introduction

Now we're going to spend a little time talking about DOM cleanliness, but users never
see the DOM, so why do we care how clean it is? We'll start with some simple things. A
clean DOM means no extraneous nodes, which helps with our CSS, especially if we're
using positionally-sensitive selectors such as nth child. The extra DOM nodes could
present a problem. Next the potential for extra DOM nodes presenting
accessibility concerns, for example, for screen readers. And now the big reason, all that
stuff about it being better for end users is true, and great, and all, but I'm a
developer, and developers don't care about users, all we care about is ourselves and
other developers, right? Well, okay, no. All kidding aside, I think the biggest reason for
a clean DOM is just simply that it makes debugging a lot easier, and if you think
about that, while it directly impacts us as developers, it does also benefit users,
because we can fix bugs faster, and if we spend less time debugging, we can spend
more time working on features, and that's good for everyone. The simplest way to
clean up your DOM is just to use ng-container wherever you can. We covered ng-
container earlier when talking aboutngTemplate in the section in the course on
dynamic UIs, so I'm just going to mention it here as one really easy way to clean up
your DOM. If you're not familiar with ng-container, you'll see it throughout the demos
in the whole course really, and it's just as simple as what you see on the screen here.
Instead of using an HTML element like a div that's going to add to the DOM, use ng-
container, which doesn't add anything extra to the DOM.

Component Attribute Selectors

Moving on to other clean DOM tricks, and attribute selector on a component is a twist
on the typical selectors you're probably used to and available simply because
underneath the Angular covers,components are just directives with a template and
potentially a style sheet. Typically you specify the selector like this in the component
decorator. Use them like this in a template, and they produce the output like this in
the DOM. No big deal, and what we all use most of the time. I can think of a few
scenarios where maybe this isn't what you need though. In any event, the app-comp-2
element is just noise, it provides no value. Wouldn't it be nice if we could get rid of
that extraneous element? As you would expect, the good news is that we can,
easily. All we have to do is specify our selector inside square brackets like this, use it as
an attribute on a standard element, and it results in a cleaner DOM like this. There's no
difference in the UI, so this isn't something that the user is going to see, but it's going
to be easier for us to work with either in debugging, or in our initial development, or in
maintenance development. So you can see here on the screen in this attribute selector
widget, I have two different child components present, well the same child component
presented twice. I'm using what I call the normal selector, and then for the attribute
selector, it also says This is the child component. So let's open up the dev tools, and
take a look at what we have going on here. So starting just to get our bearings, starting
from the heading for our normal selector, inside that we have a div with a class
of myClass, and inside that we have our element for our child component. Contrast
that with what we have for the attribute selector, here's the heading for the attribute
selector, inside that we have our div with a class of myClass, but that div is our child
component now. We don't have a separate element for the child component. So a
small piece, but if you're using this consistently, it's going to start to add up. And I
don't think this is going to have any noticeable impact on the speed, but if you need to
go through and be working inside the DOM to debug a problem, I find it a lot easier
to have a cleaner DOM to work with. The fact that it's really easy to get this is also
another selling point, so let's take a look at that. Inside our child component, the only
change that we need to make is here. You'll notice on our selector for the component
we have the typical selector that we would use, but then we also have an attribute
selector specified. Everything else is exactly the same. When I go and want to add
that component in, I can do it one of two different ways. I can do it what I call the
normal way and use the element selector, or I can add it just as an attribute on to
another HTML element, so in this case I'm using a div, and I just use that
attribute selector to specify that I want to insert the child component there.

ngIf to Minimize DOM Size

Here's a chunk of the DOM from our demo application. It doesn't look too bad, a
simple grid actually using Angular material, but that's neither here nor there. It's just a
chunk of HTML. To debug this in the dev tools, we simply expand and collapse the
nodes to find what we need to review, or use the element selector tool to zoom right
in. But there's a problem with this, and maybe some of you caught it. All of this HTML
shown here, yet none of it's showing in the UI because of this, but all of it is in the
DOM, which means that if we're debugging, it's in our way. If we're not paying
attention, we could end up wasting time here. Too, this is DOM that needs to
be parsed, displayed, and managed by the browser taking time and memory. Another
problem is that the change detector needs to worry about this part of the DOM
too. And it's all because we did this in our template, set display to none. This is a very
jQuery type approach that just doesn't work well in Angular. We could've just as easily
ended up with this and had the same problem. We'd get that if we had used the
hidden attribute instead of setting the CSS styles. From a DOM cleanliness point of
view, this is much better, and it achieves exactly the same UI for our end users, but it
has none of the noise that's just bloating our DOM. And all it took was using ngIf to
actually remove all those extraneous elements from the DOM instead of just hiding
them. The discussion on ngIf so far has been strictly one of DOM hygiene. Later in the
course, we're going to talk about UI performance, and one of the things we'll discuss is
that DOM manipulation is expensive, repeatedly adding and removing things from the
DOM can have a significant impact on performance, ngIf can certainly add to those
problems. So a few simple rules for ngIf that can help to mitigate any
potential performance impact: Don't just toss ngIf into your code base willy-nilly, be
selective in its use, look at other options like ngTemplate or dynamic components if
those could help. If you are using ngIf, put it up as high in the DOM branch as
possible. Know how often your DOM is going to potentially change, and use that as a
guide for using ngIf. The less option your DOM changes, the less of an impact adding
and removing items from the DOM via ngIf will have. As I said, we'll talk about
performance and change detection later in the course, so we'll touch on all of this
again. I just wanted to make sure to at least mention it here, because I advocated for
ngIf from a DOM-hygiene point of view as being a good thing.

ngSwitch Bloat

This is more on the HTML template side as opposed to the final DOM, but ngSwitch is a
headache to work with. Now I'll readily admit that my sample ngSwitch here is a little
forced, but we've all probablyeither seen something like this, or seen a situation which
could devolve into this as more ngSwitch cases are added. No matter how you slice it,
ngSwitch is just a bulky construct. Instead, why not use ngTemplate to define the
template somewhere in the page, and I'm fond of putting them down at the bottom
out of the way, and then using ng-container in conjunction with
ngTemplateOutlet, which we looked at in the module on dynamic UIs to pull in the
appropriate template. That makes our ngSwitch less verbose, it doesn't contain the
actual content, just references to it using ng-container, ngTemplate, and
ngTemplateOutlet. Now that's pretty good, but if we're trying to keep our HTML
as concise as possible, we kind of need to ask why we're using ngSwitch at all. It's a
pretty big block of markup almost no matter what you do. What if we could get it down
to just a one liner like this. I'll be honest, I rarely use ngSwitch, as I found this approach
much easier. Plus all of my logic is now in my type script, which I find easier and better,
my HTML template is about as dumb as I can make it, just displaying whatever it's told
to display. Let's go take a look at both of these options in our demo application. So
we're going to take a look at three different ways of implementing a switch control
functionality. We have our typical way, which is a ngSwitch, we'll take a look at all
three of these in the HTML in just a moment. We're going to go through an augment
ngSwitch, which produces the same output, but in the HTML it's less verbose. And then
we're going to look at totally replacing ngSwitch, which again gives us the same output,
but it gets us down to a much, much smaller footprint inside our HTML. Changing
these by changing the value of my switch variable, and they all produce the same
output.Taking a look at this inside my code, we'll start in the HTML, just a simple
button that changes my variable. We come down, here is our typical ngSwitch, and we
have a ng-container with the ngSwitch bound to our first switch variable, and then all
of our HTML is complete in line. You can see here's Case a, Case b, Case c. Now these
are a little bit stilted, I intentionally built them this way to make these appear larger
and take up more room in the HTML, but it's not that much of a stretch, I've seen some
pretty big switch statements inside my HTML. So here we go from line 8 down to line
46, and that is my first switch statement. It's fairly big. We can augment that by making
use of ngTemplates. So here we have from line 53 down to line 66, so considerably
less space, a smaller footprint inside our HTML file. As we saw in the browser though,
the output is exactly the same. The difference is we're still using ngSwitch, we're using
a different switch variable, just to keep everything separate. Then we have more ng-
containers, which aren't going to put anything into our DOM, so there's no concerns
there. And then we make use of this *ngTemplateOutlet, and for SwitchCase a, we're
going to grab template1, for b we're going to grab template2, and for c we're going to
grab template3. If we hit the default, we're just going to print out default. Those
templates are defined down at the bottom here. As I've said before, I like to put
my templates down at the bottom, because then they're out of my way, I don't need to
worry about them, unless I'm explicitly working on them, then I'll scroll down to see
them. So here is where the bulk of the content is still specified, but as I said, it's not in
line, it's much easier to work with 13 or 14 lines than what we had up top here. So
that's pretty good, but what if we could get it down to just a one liner, and that's
exactly what we get here by making a call out to a function for our ngTemplateOutlet.
So we have a ng-container *ngTemplateOutlet binded to the output of this
getTemplate, and that's what's going to get displayed. So taking a look at the code, we
have our ViewChild decorators on our properties to go and get the different templates,
so template1, 2, and 3.As I said, I have three different switch variables just to
keep everything, each instance separate, and then here is my getTemplate, and it's
going to say in code I'm going to be doing a switch here, which I think is the proper
place for it, I think it's a lot more concise, and it's easier to work with. So I'm still using
these templates down at the bottom, but my actual switch statement in my HTML is
down to just a one liner, much, much easier to work with, and I find the separation of
presentation and functionality easier to work with as well.

Shadow DOM

If you're somehow lucky enough to be able to support only Chrome 61 or better, then
you can switch your view encapsulation, which we talked about earlier in the course to
Native. That means that Angular won't need to add any specificity to your selectors, so
you can work with a cleaner DOM and cleaner CSS when debugging. it means going
from this with view encapsulation set to the default ofemulated to this with view
encapsulation Native. Now it's not a lot, but every little bit helps, if you're lucky
enough to be able to take advantage of it. Like I said, this is only Chrome 61 or better
as of early 2018, but hopefully other browsers will jump on board before too long.

Wrap Up

This module was all about DOM hygiene, why it's important for users, but more so up
for us as developers. We covered the different options shown here to keep our DOM
as clean as possible and discussed why that's important. Next up, we're going to focus
on improving the performance or theperception of performance in the UI. This
includes a discussion on change detection, the impact of UI lifecycle hooks, some neat
tricks with typescript that can improve performance, impure pipes, and a lot more.

Improving Performance of the UI

Introduction

Here's the thing, Angular is already pretty fast. There may not be a whole lot you need
to do in order to get your application's performance into acceptable bounds. Yes,
faster is better, and you want the best performance you can get, but you'll reach a
point of diminishing returns. Each application is going to have its own level of
acceptable performance, once you hit that, the cost of squeezing out justslightly better
perf is likely to start skyrocketing. Two, consider your audience and their expectations,
as well as their ability to actually perceive performance. On the surface if option B is
twice as slow as option A, you probably want to look and see how hard option A would
be to implement. If that 6 seconds versus 3 seconds, I'd say that make sense. If it's 600
ms versus 300 ms, maybe not so much, except in very specific situations. In that ladder
case, it's likely your audience is probably not evengoing to notice. Specifically here's
what we're going to look at. Async loading, including some pretty easy UI tweaks to
improve perceived performance even more. We'll look at using pipes correctly. Pipes
are easy and effective, but in certain situations can present performance problems. A
look at improving the performance of ngFor, especially for large collections or
collections that change frequently. A kind of advanced, but easy once you see it-type
script capability for improving performance by using custom decorators. And last,
lifecycle hooks, we'll start first with general guidance and an overview of the lifecycle
hooks to understand their performance impact, and then dig deeper in the second part
of our look at lifecycle hooks to get an understanding of how the hooks impact
our programming in the UI.

A Better UI for Async Loading


Asynchronous loading of content is practically a given these days. Often what you're
doing is reloading a small subsection of the page, but it would still be nice to show
some type of loading message orspinner here too. There's certainly multiple ways to
solve this problem, and we're not focusing on the actual async operation here, we're
sticking with the UI aspects, but I think the ngTemplate approach is about the easiest.
We start with our conditional for the ngIf, which in this case is our asynchronous
observable, and here we're telling Angular to store the results in the cust template
local variable. Before the observable is complete, my observable is null, which is falsey,
so the ngIf loads the loadertemplate, which contains a component to show a loader
message, or a spinner, or whatever we need. When the observable returns something,
my observable is no longer null, so the ngIf switches todisplay the in line template, in
which we can use the cust variable to access properties of the object returned from
our observable. There's a couple of moving parts here, so let's break it down in our
sample application. We're looking at the UI aspects of asynchronous loading, not the
actual mechanics of how you go about loading something asynchronously. Like I said,
we're focusing strictly on just the user interface experience. So when I take and load
up my async loader widget, you'll notice that it displays a loading message until my
information is available. So you could have an image there, or whatever you wanted, I
just have text to try to keep things simple, and the nice thing is that gettingthis is
really, really easy. Taking a look at my HTML, starting down at the bottom, I have
my template that defines what information I want displayed while I'm waiting for the
asynchronous call to return. So here's where I just specify the text loading, you could
put an image in here, a countdown, whatever you wanted. Up above this, I have my
ng-container, where I'm going to be putting my content, and this is the real meat of my
component, but what I start with is an ngIf hooked up to my observable using the
async pipe, and until the observable comes back, until that call resolves, this is going to
be undefined, which is falsey, which means that the ngIf is going to load or is going to
use the loader template. Once my observable has returned, then it would have a
value, it now becomes truthy, and it's going to display the information in the inline
template. I can specify the context variable, so that I can reference it here just using
simple interpolation. Inside my code, I have an observable, now I just have this set up
for the demo with a simple timeout, but if you were making a callback to a server, to
retrieve the data, whenever you call observer.next when your data has returned, that's
when the loading message is going to disappear. So a very easy, kind of clever
approach to displaying a loading message to users while you're waiting for content to
come back from an asynchronous call.

Pipes and Performance


Most out-of-the-box pipes will be called or will process their inputs to update the
display, only on pure changes. That's not very helpful, what's a pure change? A pure
change is one of two things, when your pipe is attached to a primitive data type, and
that primitive value changes, or when your pipe is attached to an object, date array, or
function, and the reference to it changes. JavaScript can verify these types of changes
very quickly. So it can tell if it needs to process the pipe and then update the view
without any real impact on your application. So if you're using a pure pipe and change
a primitive value or a reference used as an input for the pipe, Angular will process the
pipe and update the UI. It ignores any other change. This is the default for pipes. The
last thing to know is that because pure pipes use pure functions, that is, I mean
functions that always produce the same output when given the same input, using a
pure pipe on a page multiple times only requires a single instance of that pipe in
memory. Not a big deal from a performance perspective, but every little bit helps,
especially when it doesn't cost us anything. The other option available for pipes in
impure. Impure pipes process on every change as part of every change detection cycle,
and updates the view each time. This means that for every value change, and if you're
listening to them, every mousemove, every keystroke is going to rerun the code in the
pipe, even if the value the pipe is attached to isn't what changed. There's a good
chance that the performance of your application is going to be affected in this case.
Making a custom pipe impure is as easy as specifying false for the pure property in
your pipe decorator, but you really ought to think long and hard about making or using
an impure pipe. This demo is really more about what not to do than what to do. I want
you to understand the implications of impure pipes. So load up the widget, going to
open up the console, and can see some numbers down there in the console. Essentially
what's happening is that every time the pipe is processing its input, it also logs
the number to the console. So, you can see the directions here, I'm going to wiggle the
mouse around in this gray space, this gray block, and you can see the numbers just
streaming by inside the console. That's almost 600 times now my pipe has processed
its input. The input didn't change, it's still just the word hello,but every time in this
case the mousemove event fires, it's going to reprocess, because it's an impure pipe.
So let's take a look at that so you understand how we got here. So I have a div, this is
where mymousemove event is registered, and then down below it, I just have
an interpolated piece of text being piped through my impure pipe. The code in the
background here is the mousemove event, it doesn't actually do anything, I just
needed it there for this demo. And then the impure pipe itself, here's how you set a
pipe to be impure, but as I say in the comment, really think about this, because you
could really strangle the performance of your application if you use this incorrectly. So
what all this is doing is logging out to the console just a simple counter, and then it just
returns whatever value it came in, so that's the word hello, and then just that fixed
string at the end there. So you can see the implications of impure pipes, they process a
lot. Impure pipes and mousemove events, probably not a really good idea. So the real
lesson here is be careful with your use of impure pipes. For the most part this isn't a
huge problem with the built-in pipes, because all except for three of them are pure, so
don't have that much of an impact. The three impure pipes are splice, not a big deal, I
don't know many who use this much im production, JSON, again not a huge deal as it's
not used much outside of debugging, the third one though is a potential biggy, the
async pipe is really useful and really common. I get why it needs to be impure, but to
be honest, I don't have a really good answer for how to reduce the potential
impact. I'm not saying don't use it, but just be aware of the fact that it has potential
performance implications. The other thing to keep in mind about pipes is if you're
building a custom pipe, try to keep it pure if you can. I'm sure that there are reasons to
build impure pipes, but honestly I'm at a loss to come up with a good scenario for
doing so. Impure pipes should be the exception. The other thing about building custom
pipes, especially if you build an impure pipe, but even for pure pipes this is important.
They shouldn't do a lot. Pipes need to be small, very fast operations. A pipe isn't the
right construct to use if you need to perform complex, time-consuming operations or
make calls to external servers. If that's what you need, that code belongs inside your
component where you can control it better.

A Better ngFor

Everybody knows about using ngFor to iterate over a collection and stamp out
templates into the UI once per item in the collection, nothing special here. However if
you're working with large collections, you have a potential performance problem on
your hand. Here's the scenario. You store the items in some type of object array. You
probably initially get that collection from a server and then periodically get an updated
collection of items from the sever and update the variable that the collection is stored
in. The problem is that when you update the collection, Angular by default wipes out
every DOM node added for the collection and recreates nodes for the new collection
item. It does this because it doesn't know how to determine which items are already in
the collection and can be left alone. That gives it no choice but to wipe it all out and
start clean. Most of the time this isn't a problem. We're probably not displaying huge
lists, and so no one's going to notice the UI flash as Angular wipes and recreates a large
portion of the DOM. But the fix for this is so easy that there's no reason not to
justmake this our default approach for ngFor even for small collections. We do this by
telling Angular how to uniquely identify each item in the collection. So when it's
determining which items were added and removed in the new collection, it has a
unique identifier to start with. It then only needs to remove the nodes for the items in
the initial collection, not in the new collection, and add new nodes for the itemswholly
new in the updated collection. We do that by providing and specifying a trackBy
function. The trackBy function simply returns a unique identifier for each item in the
collection, here I'm simply using an id property. Let's go take a look at the problem and
the fix in our demo, and I think you'll agree that this is a no-brainer way to improve
performance for any size collection. Setting a trackBy function on your ngFor is pretty
easy and can have a nice improvement in your UI, especially if you're dealing with large
lists. So taking a look at what we have, bring up our widget, and then I want to go into
the dev tools, I realize that the dev tools are probably a little bit hard to see. The
important thing is not seeing the details, the important thing is to watch as I click on
the update list, we have two ngFor's, one without a trackBy and then below that, one
with a trackBy, and they're both working off of the same lists, so when I click Update
Lists, they're both going to get updated. So keep an eye on the dev tools over on the
right-hand side there, because they're going to flash to show which elements have
beenchanged in the DOM. So you can see up top everything changed, and down below
in the one with the trackBy, just the last two changed. Now when things get interesting
though. I'm going to update the list again, but nothing actually changes, the values all
still stay the same. In the top, all of my items change, but nothing down the bottom
does, because all the values are still the same. So here we've got a list with, what five
different items in each ngFor. You don't see anything in the UI, but if you've got larger
lists, it's conceivable that people going to see a flash where things are going to be
completed wiped out and then added back in again, and that's not what you want. And
even if they don't notice it, it's extra work that Angular doesn't have to do, because it's
really easy to avoid it. Taking a look at the code, here's our HTML, you can see I have
my Without TrackBy and my With TrackBy, and the difference is specifying a
trackbyFunc at the end here. Other than that, these are exactly the same. So I'm telling
my ngFor to call this function for each item to uniquely identify them in the list. That
trackBy function just needs to return a unique id for each instance in the list, each item
in the list gets a unique id. My list itself is a simple object, it's just name and id. When I
update the list, I change it, and the items that change are these last couple at the end
here, one, three, and five stay in the list, two drops out, seven and nine get added. So
that's where we see flashing in the browser tools is items being dropped out and
added back in, and without the trackBy, Angular has to drop everything out of the list,
and then add everything back in. With the trackBy, you can just say okay, drop two and
four, add seven and nine, and we're done. And then when I click that button a second
time, and update the list to the same values with the trackBy, Angular says I don't need
to update anything, so nothing flashes, nothing changes in the UI, whereas without
the trackBy, it wipes everything out and adds it all back in again. It's just extra work
that Angular doesn't need to do.

Instant Caching with Memoizing

Everyone has an opinion on what you can do to make your code fast. There are,
however, very few things that can be said to always without fail 100% of the time
make your application faster. I'm going to give you one of those things though, and I
can guarantee that it absolutely, positively 100% is true in all situations. The fastest
code you or anyone else has ever or will ever write is code that doesn't run. Now wait,
what does that mean, what good is code that doesn't run. Right now you're probably
thinking Dave's lost his mind, but bear with me. If the code doesn't run because
it doesn't have to, but you still get the exact same results as if it had run, well that's
pretty good, and if you're thinking about it, that's all caching is. The code runs once, it
generates a value, or values, or whatever you need it to generate, and then it stores
the result. Next time and potentially many times after that, the code doesn't have to
run to get that value, it just returns it from cache. Until the stored value is no longer
correct, there's no need to go back to the source and regenerate the value, the cached
version is fine and likely much faster. But caching is not a panacea, it comes with its
own requirements, which can add significant complexity. You need to manage the
cache, and some point be able to knock stored values out either because you need the
room or their no longer valid. Caching adds potential security concerns. You need to
think about how and where to store the cached items. And finally there's extra logic
your code needs to have to first check for a cached version of the data it needs, and if
that's notavailable, then go retrieve it from the source. But what if there were a way to
get all of the benefits of caching with very little work and with very little of this
complexity? We can do this with a computer science technique called memoizing, and
we can do it pretty easy with typescript custom decorators.Let's go take a look in our
demo just to see how easy this is. Memoizing is really a pretty painless way to set up
caching, and it can really be helpful for reducing the impact of, for example, server
calls. So here I have my widget set up, and every time I click this button, I'm getting a
new value. I don't have the memoized decorator on currently, so you can see in the
console window, every time I click the button, I go back to the server. Now I'm just
simulating a server connection here as we'll see in the code, but I'm still hitting it every
time I click the button. The code for this, starting in the HTML, pretty simple, the
button calls getValue, and then I have a property that I bind, I interpolate and present
the information, present the value, just back on the screen. The typescript behind it,
really two main pieces, here's the function that gets called by the button click, it's
subscribing to an observer that's simulating a callback to the server, so getFromServer
just uses a 100 ms timeout to simulate a server call, generates a new value, and hands
it back. When this gets that response, when it gets the information back from the
mock server, it's just going to set the value of this server value property to whatever it
got back, and that's what's bound into the UI, that's what's presented. If I go and
uncomment my decorator, jump back over to the browser, go ahead and click this, you
can see that it's only going back to the sever every five seconds. That's the way I have it
configured. No matter how many times I click this button, it's only going to go back and
refresh the value every five seconds. So what does that memoize decorator do? What
that does is call this code over here. Starting at the top here is the memoize function
that gets called, and it takes a number of seconds that you want to timeout, after five
seconds in my case, it's going to hit the server again. Ultimately what happens if we're,
typescript is going to be rewriting our function, so that when we call our getValue, it's
actually calling a new function created by the decorator, and what the decorator
does is it sets up an object that stores the values, so you can have multiple things
memoized at the same time, multiple functions or property getters. So the function
that gets written in place of our original function is this one right here starting on line
13. Again we've set rv, our return value, we check to see whether or not we have a
memorizedor memoized return value. We check to see whether we have that property
and the timeout property for that is still greater than the current date. If it is, then
we're just going to return whatever is stored in that property. We don't have to go
back to the server for it, because we have a cached version. If we don't have a property
or it's timed out, then we're going to call our old function, which was what was passed
in as the original function, and we store that. We call the old function, get the
value from it, and then we define a property to store it in propName, and we also
create and store the timeout information. So the timeout property is going to be the
current date and time, plus whatever number of seconds you want to wait for the
timeout, and then we return the return value out of that, so the return value from the
original function call. The next time it comes through, we're going to have that value, if
the timeout hasn't expired, so we're just going to return it, we don't have to go back to
theserver for it. So I can take this memoize and put it on any function that I want, and
pass in the number of seconds that I want it to wait before timing out, and that gives
me a pretty easy way to improve theperformance if my values, if my data isn't
changing, and I don't need to have, you know, up to the millisecond updated content
displayed on the screen. Some applications this definitely won't work for, some it
will, and those are the ones that we can target to say, I want to wait every 3 seconds, 5
seconds, 10 seconds, hour, whatever amount of time you want to keep that
information cached, just by changing the property, the parameter that's passed in to
the memoize function. Now of course the memoize decorator is only going to work as
long as the JavaScript function that called it is in memory, so you want to be aware of
that if you have that function in a component, then the memoization is going to go
away when that component is swapped out of memory if you navigate to a different
component, for example. Now it will get recached, rememoized when you come back
to thatcomponent, but if this is something that you want to have available from
component to component, then you probably want to think about moving the function
that uses the memoize decorator into a service, which would allow it to survive
component reloads.

A First Look at Angular's Lifecycle Hooks

There are effectively nine hooks available to us. I say effectively because one isn't
really an Angular lifecycle hook, and others are only available in our components, not
our directives. Let's take a look, but we're going to do this in waves, first a
quick overview of the nine, and then we'll dig in deeper. First up is the not really a
hook, and that's the constructor. Like any other objects, the constructor fires when an
instance of the class is created, and while it should be used to set up the object, it
should also be very lightweight. The constructor only fires once per instance. Next up is
OnChanges, OnChanges fires once when an instance of the object is created, just after
Angular sets databound input propertieson the component or the directive, and then
again whenever a bound input property changes. Next is OnInit, this one fires only
once, and it happens after the first OnChanges. You've likely seen and used this one
before. DoCheck comes next, and it's sort of the catch-all for things that may not get
picked up by Angular's change detector. It gets called as a part of every change
detection cycle.AfterContentInit is called after Angular has injected external
content into the component's host view. This is also the first of our four hooks that are
only available in components, simply because directivesdon't have a view. It's fired
only once. The next hook is AfterContentChecked, and it's also a component-only
hook. It fires after Angular has checked the external content injected into the
component's host view. AfterViewInit is another pretty common hook, so you're likely
familiar with it. It's another component-only hook, which fires once, after Angular has
initialized the host view and any child views of the component. Next,
AfterViewChecked, this is the last of the four component-only hooks. It's called after
Angular checks the host view and any child views. The last hook we can respond to
happens only once when Angular is just about to destroy our classed instance. There
isn't a whole lot we can do here, and we can't stop the instance from being
destroyed, but this is our last chance to do anything with the component. We're not
going to take a look at it right now, because it's prettybasic and pretty straightforward,
but I did create a little playground widget you can use to explore the different events if
you're interested. It's in a widget called Lifecycle Hooks. Here's what it looks like. On
the left-hand side it shows a running log of each hook that gets fired, along with a
timestamp. In the middle it shows the name of each hook and the last time it was
fired. At the top, there are a couple of opportunities to see how different changes call
different hooks. There are buttons to change an inputvalue passed in from a parent
component, one to change a simple local variable, one to inject a template into a view
container, and a div with a listen on it to trigger a bunch of mouse move events.One
interesting thing to take note of is the addition of the OnChanges hook when changing
an input variable compared to just changing a local component variable. The bulk of
the code in the Playground Widget looks something like this. It simply uses a function,
which is recognized by Angular as the oneto be called for each hook, and records the
fact that the hook was fired. While not technically required, the easiest way to work
with these hooks and get these specially named functions right is to have yourclass
implement the interfaces supplied by Angular like this. Each function name is simply
lowercase ng followed by the name of the hook, as we can see here with ngOnInit. Feel
free to explore that demo widget if you're curious about which lifecycle hooks fire
at which points in your code. We're going to move on to some additional information
about working with lifecycle hooks and their impact on performance.

Working with Angular's Lifecycle Hooks

Now that we've been introduced to the lifecycle hooks available to us and seen the
sequence they're called in, let's dig a little deeper into their use and their impact on
performance. As I mentioned before, this isn't really an Angular hook, but it plays an
important part in our lifecycle, so we're going to take a quick look at it. The constructor
is the first code that runs when a new instance of a class is instantiated. You may be
tempted to do all of the initialization here, so that your object is fully hydrated
and ready for use, but that's not a good idea. For many reasons, not the least of which
is to facilitate easy testing, your constructor should be as lean as you can possibly
make it. In general, anything more than initializing simple properties to default values
is probably too much for work in a constructor. When the constructor runs any
properties, local or bound inputs, have whatever value they're given in their
declaration, also any properties representing query children, for example,viewChild or
contentChild are undefined. After the initial component load, OnChanges fires any
time a bound input property is changed by a parent component. It receives a
SimpleChanges object representing the changes that were made to the property,
specifically showing the property name and the current and previous values. It's the
only true hook that receives a parameter. This hook is similar to the pure pipes we
talked about earlier in that it only recognizes changes to primitive properties or object
references. This means it isn't going to pick up a property change on a bound object,
only if the object reference itself changes. We're going to take advantage of this in the
demo in just a bit toprevent extraneous hooks from firing. When this hook fires
initially, bound inputs now have whatever value they're given from their
parent binding, overwriting their declared value. Also, any properties representing
query children, for example, viewChild or contentChild are now set. However, they're
not fully processed, so you may not want to do anything with them here. When talking
about the constructor, I mentioned that they should be as lean as possible, not doing
any real work. So when do you fully initialize an instance, in OnInit. This is the time to
perform steps that are too much for a constructor like fetching data from remote
servers, or creating other objects, etc. While input properties are technically first
available in the previous hook, OnChanges, that hook is potentially called many
times, whereas OnInit is only ever called once. This makes OnInit potentially a better
place to do any initial work with those property values, and then use OnChanges to
perform subsequent work. Queried children are also first available in OnChanges,
though as I said, they're not fully processed. That doesn't happen until
after ContentInit, so you want to wait before doing anything with them. Finally in
components, this hook is called before any of the child directive properties are
initialized. While Angular's change detection is very good at picking up changes, it's
dangerous to think that it's always going to pick up every change, there are just too
many opportunities for things to change in our applications. And this is one of the
reasons that the Angular team gave us DoCheck. It's our catch-all, our chance to inject
something into every change detection run for a component, its parent or any
siblings. Let me restate that, because it's important. DoCheck runs as a part of every
change detection cycle for a component, its parent, and any siblings. Think about that
for a second from a performance perspective. If you have a handler for the DoCheck
hook defined on this component, and the change detector is triggered on its parent
component or a sibling component, that handler is going to fire on your
component. This is a potentially huge impact to our performance if you do anything
significant in DoCheck. For this reason, be very careful with the code that you put into
this hook. If it takes more than a handful of milliseconds, it's probably too much. After
ContentInit is called once, after content has been projected, and all children of the
component, including projected children are fully initialized, checked, and ready for
use. We talked about queried children earlier in both OnChanges and OnInit, but said
they weren't fully set up yet. At this point, content children are, so this is the first point
where you can really work with them. The previous hook, after ContentInit, is called
only once, when the component and any children are first set up. This hook,
AfterContentChecked, is called in subsequent changes and serves the same purpose.
Content children are fully updated in this hook and ready to be worked with. Note that
this hook fires even if the projected content hasn't changed, so this one also fires a
lot. Like DoCheck, be careful not to do too much here. This is the view counterpart to
AfterContentInit. This is when view children are fully initialized, checked, and ready for
use. This is the first place that you really want to start working with them. This hook is
also analogist to the earlier AfterContentChecked, like that when it's called in
subsequent cycles, but again for view children instead of content children. This is
where you want to work with view children in subsequent change cycles. Also like after
ContentChecked, this one is potentially going to fire frequently when they're not
actually any changes to your view children, so be careful how much work you do
here. Finally, OnDestroy, called just before our component or directive is destroyed,
and so a good place to do any necessary cleanup such as unsubscribing from
observables and detaching event listeners. We're going to take a look at another
playground-type widget I put together to help us explore the hooks further, focusing
more specifically on what properties and values are available or change at each point
in the process, let's go take a look. Looking at our second lifecycle hooks widget, this
shows us what information is available and what values have changed for
different types of changes in our environment. So you can see when I first load this up,
we have a box with the constructor and then the eight different lifecycle hooks.
Anything that's tan has been fired in the current run. Anything that's yellow is anything
that's been changed. Now it's a little off between the constructor and
ngOnChanges, you can see both, two things being yellow there, because we've
got them being updated rapidly one right after the other. When I go and click on a
button, you can see again the tan boxes are the lifecycle hooks that fired, and what
changed is going to be highlighted in yellow in the first box that it changed in, local
primitive values, bound objects, just a property, and then bound object
references. Across the top here, we have just a dot that shows up every time a hook is
run, so you can see when I click this, it increases by the number of hooks that ran, so it
went up three that time, four that time. The code behind this isn't as important as
getting familiar with the results from it. Starting in our widget component, it just has
a child component called hooks2. We pass in a boundPrimitive and a boundObject, we
have a couple of outputs that we're setting up for our buttons. In the widget host
component itself, we have some functions, these get bound to the output, we have the
object that we're working with, we have the primitive that we pass in. In the hooks2
component, this is a little bigger, because it has all of the buttons in it for doing the
changes, and then it has the table that contains all of the different cells, one for each
lifecycle hook. You can see each one has a template reference variable, that's how I go
and access it. We changed the color based on whether or not that hook has been fired.
The bulk of what's going on is inside the component typescript file. There's a lot of
code in here, and none of it is particularly difficult, all of it is there to handle
recording when each of the different hooks fire. Now most of the time, it's fairly rare
that you're going to respond to every hook that Angular fires. So you're not typically
going to have a lot of the code that I have in here, I'm actually going through and
working with some of the sanitization, which we're going to cover in a later module, to
be able to display some of this information on the screen, and I have code in here to
record current and past values of different parameters that are passed in, or properties
that are passed in, and a lot of stuff that you wouldn't have in a regular application, but
are important when you want to be able to track each of the lifecycle hooks when they
fire, what properties they've updated, whether or not they're the first item to update,
etc. So feel free to look at this, I'm not going to go through this line by line because it's
pretty long. But you can see the main thing that it's doing is when you get down
in here, starting on line 78 with our constructor, we're basically setting values that says
okay, so the constructor has run, we set up some variables, and then we're going to go
out and get the sanitized values that we can print to the screen. Then we say the
constructor is done running. We're going to do the same thing when ngOnChanges
fires, so we recordthat it's running, we get the values for each of the things that
we're concerned about, our bound primitives, and local primitives, and bound objects,
and local objects, etc., and then we go and get asanitized string that we can display on
the screen to show those values, and then say that this particular hook is done
running. So that's the pattern that gets followed for each one of the lifecycle
hooks. And then down below there's some supporting code for doing things like the
sanitization, storing previous values, etc. So feel free to take a look at this code, like I
said, there's a lot here that you would not normally have in a typical application, but in
order to capture and work with all of the different hooks, I needed to put a lot of this
stuff in here. So again, the important thing to get out of this playground widget
and really the other, the first lifecycle hook playground widget is what changes in
different scenarios, and if you want to see what changes for the OnDestroy, we'll just
go ahead and switch to a different widget, I couldn't update the UI because it would
disappear, I needed something that would freeze the screen, well I pop up an alert that
just shows some of the information and what's available in OnDestroy.

Wrap Up

We covered a lot in this module, but remember, Angular is already fast, so you may
not need all of what we discussed. Knowing that you now have these things in your
toolkit means that you can use them when you need to though. The next thing we're
going to talk about is security, specifically cross-site scripting and input sanitization.
Security in the Angular UI

Introduction

Angular treats the UI as a DMZ, accessible to anyone untrusted and


untrustable. Mostly this is good and exactly what we want. Sometimes though we
need to tweak things just a little. Before jumping in and doing so though, it's important
to understand how Angular secures things by default and exactly what risk, if
any, we're opening our application up to if we bypass the built-in security. In this
module, we're going to explore the default security settings and then talk about how
and why to override them.The most important thing to understand before beginning
any discussion of security is exactly what the threat is and how it can present itself to
our applications. While this isn't a course on all possibleweb security vulnerabilities,
we're going to cover the primary one that comes into play for the UI portions of our
Angular apps, cross-site scripting. Specifically, we're going to take a look at what XSS is
and how Angular protects us by default and then finish with a look at why and how we
can override the defaults that Angular establishes.

Understanding the Threat

Starting with the basics, if you're not familiar with XSS at all, here's a pretty concise
definition. But what does this actually mean? It really just comes down to this. We
want to stop people from being able to somehow add some random script to our site
and have it run, not in their session, but in another user's session. Why don't we care
about their session? Well it's not that we actually don't care, but the primary thing
we're protecting against is letting the code run as another user when it will presumably
have access to that other user's session information and any personal, financial, or
other information stored in our application. The user trying to inject the script already
has access to their own information. We want to stop them from getting in someone
else's. Any content received from users is a potential attack vector. This isn't an
exhaustive list, but here's some of the more common possibilities. Forms. Any type of
form, sign up, contact, request, whatever, anywhere a user can enter information that
gets submitted back to the server. Any URL. To me this is one of the trickier ones that I
probably wouldn't have thought of on my own, but I guess I don't have the proper
hacker mindset. A search box. This often works in conjunction with a URL injection
where hackers craft a URL that includes a script tag. They obfuscate it and then send it
to people. Anyone clicking on the link is going to visit the search page of the site, which
often mirrors the search term back on screen sayingsomething like this, which if that
text isn't sanitized is going to execute whatever script was injected. And finally people
could inject random script via comments. Again not an exhaustive list, but certainly
gives you some good examples to think about. The last thing to cover is the fact that
protecting against XSS means more than just blocking script tags. If users can somehow
create event handlers or create links, you're open to XSS attacks. This looks to be
remedied now, but in some older browsers,certain CSS selectors were able to execute
JavaScript as well. Now you may think this is some pretty far-fetched scenarios. I mean,
why on earth would you ever let or allow a user to create an event handler? The
problem is that it's not what you intentionally allow that gets you in trouble. It's what
you inadvertently allow to happen. You need to be right 100% of the time. Someone
attempting to hackyour site only needs to be right once. One last point before we
start looking at Angular's default protections. Don't think that you're safe just because
you're not building a public-facing site. Most attacks come from inside the firewall, so
employees, contractors, etc. We didn't even scratch the surface of the problem of
XSS, just touched upon certain types of things you need to understand. If you want to
dig deeper into this, I highly recommend this course by Troy Hunt. You can also see
other related courses here.

Default Security

This is Angular's default approach to security. Pretty straightforward. The answer to


the question does Angular trust this value is no. Angular goes a step beyond just
distrusting values from the user. Rather than try to blacklist all the things it
distrusts, Angular simply whitelists the small number of things it does trust, none of
which are values. The things Angular trusts are your template HTML, binding
expressions, and attributes. That's it. But what does it mean to say that Angular
doesn't trust something? Basically it means that it's going to sanitize or cleanse any
content it doesn't trust before adding it to the DOM. Sanitizing is the process of
altering the content so that it's not executable. It doesn't change what's displayed, it
just, for example, encodes it so that it isn't executed by the browser. As an example, a
piece of HTML content, which contains a script tag, is going to be converted to a string
and added to the DOM that way. It still shows on screen correctly, but the browser
doesn't parse, interpret, and execute the content as a script tag. The thing about this
though is that sanitizing each potential attack vector means different things. A string
that's dangerous in HTML might be harmless in a URL or vice versa. Because of
that, Angular takes the context of the content where it's being added to the DOM into
account when it sanitizes things. For example, the HTML shown here is going to be
treated differently depending on whether you're binding it or interpolating. We'll see
more on that in just a moment. There's are four distinct contexts Angular uses to
sanitize content, HTML, URL, styles, and resource URLs. This is important to
know because when we get to the point where we're overriding the sanitization
process, we need to do it specifically for each relevant context. So let's take a quick
look at where each context comes into play. First up is the HTML context. This is going
to be used for any content bound to the innerHtml property of a DOM element. When
in dev mode, Angular's going to put a message in the console whenever it sanitizes
some bound HTML. In this context, making the bound value safe entails wrapping it in
opening and closing quotes, so the browser treats it as a simple string to be
displayed instead of markup to be interpreted. The URL context is going to be used
when binding to our URL property, such as href. Like the HTML sanitizer when in dev
mode, Angular puts a message in the console whenever it sanitizes a URL. It's
interesting how Angular sanitizes the URL value. It actually does it, in this case, by
prefixing the bound value withthe word unsafe, which causes the browser to do
nothing with the rest of the text. Style is applied when binding to the style
property. Like the previous two contexts, Angular will let us know when it has sanitized
a style binding when we're in dev mode. For this context, Angular sanitizes the bound
value by just dropping it. And the resource URL context is for either binding to a script
source or including a script source in the tag. Here's the thing though. Resource URL is
the only context which is not sanitized per se. Instead the whole tag is just dropped.
This makes sense because the script loaded by this property is going to contain
code, which is always going to be different. There's no way for Angular to reliably clean
up any old arbitrary code. Like I said, in this case, the entire script tag is just not added
to the DOM. There's one final quasi context, which is any value being
interpolated. Content inside those double curly braces is always sanitized. Any HTML in
the content added to the DOM via interpolation is made safe, so the browser
processes it as a string, note the added open and close quotes, and therefore the script
tag is displayed, but not processed as a script tag. So the code inside it or the script
referenced by it is not run or loaded. In the UI, we still see this as literal text. Note that
the interpolated HTML is treated slightly differently from bound HTML. Interpolated is
treated as shown here where you see the script tag. But in bound HTML, the offending
script tag is actually removed, so all you see is the content.

Bypassing the Default Security

So if Angular does all of that for us by default, isn't that enough? Yes, it really is. Most
of the time, and by that I mean almost all the time, there's nothing else you need to do
to prevent cross-site scripting attacks other than what we've covered. An awareness of
the problem and how Angular works to protect our application is typically enough. Be
aware of where users are able to add content that'll be stored and then redisplayed
later. So long as you're not doing something crazy, most of the time that's
enough. Every once in a while though you need to be able to get around
the protections that Angular provides you. And just to clarify, when I say every once in
a while, what I really mean is we've looked at this and the requirement can't change
and there really is no other way to meet the requirement. At that point, you're going
to make use of Angular's DOM sanitizer class. You inject it into the constructor, like we
see here, and depending on what you're trying to do, make use of one of the following
five function. BypassSecurityTrustHmtl to tell Angular that you trust a chunk of HTML
bound to an innerHtml property. BypassSecurityTrustScript to trust a script
tag. BypassSecurityTrustStyle to trust a bound style value. BypassSecurityTrustUrl to
trust a URL. And bypassSecurityTrustResourceUrl to trust a resource URL. The return
value from each of those functions is not a string, but rather an object, which Angular
knows how to trust when bound to a property. Just to reiterate how big a deal this is,
here's the warning from the IntelliSense for one of those methods. The Angular team is
doingeverything they can to warn you about the dangers here. They're saying we're
going to let you do this, but don't blame us if you shoot your eye out. So with that
warning in mind, let's go take a look at these methods in our demo. Looking at how
sanitization works, we're going to start by just showing what things look like by default
before we go and do any bypassing. So we have a component. And inside this
component, we're just declaring a couple of strings. So we have some HTML. It just has
some simple styling and a link in it. We have an href that has as JavaScript alert and
then just a simple style string, background color is red. We take those and we
use various methods to get them into the UI. So we're going to bind to ngModel in a
text area. We're going to bind to innerHtml. We'll come down and we'll do some
simple interpolation. We'll bind our link onto the href of an anchor tag. And we'll bind
our style just onto the style attribute of a div tag. The end result of this is basically
what you see here.Without bypassing anything, inside my text area, I can see all the
markup. When I'm binding to the InnerHtml the basics, the simple styling works, but
links don't. It looks like they do, but if you look at the URL for this, you can see it's
prefixed with an unsafe. That means when I click on it, it's not going to do
anything. Interpolated, as I had said in the slides, is always going to be displayed with
the markup intact. So this is always made safe when you're doing interpolation.
Binding to the href is the same as the link we saw above. It's going to be flagged as
unsafe. And then binding to the style, well the style doesn't get applied because it's
been sanitized. To get past this, we can go back and take out these comments. We now
have essentially the same markup, but this time we're going to be using our bypass
capabilities. So in the text area, we're now binding to this safeHtml. Same for
innerHtml, we're binding to something called safeHtml. The Interpolated is also going
to safeHtml. Href is going to our safeHref, and the style is going to our safeStyle. So
what are all those safe things? Let's take a look at those. Over here you can see that
I'm declaring these types. So up in my imports, I had to make sure that I was importing
them, as well as DomSanitizer. We inject the DomSanitizer into our constructor, and
then I call into those bypass methods that I had mentioned in the slides.
BypassSecurityTrustUrl, and I pass in that unsafeHref, and it's going to give me back a
safeHref object, and I store that. So I'd do the same thing with the Html and the
Style. If I go and recompile, jump back over to my browser.Now when we come down
to the bottom here, you can see with the bypass in place, when I'm binding to
ngModel, it gives me a message here. It says SafeValue must use property=binding, so
this isn't going to work the way you would expect it to. Bound to InnerHtml, the text
styling works, and now the links actually work because we've told Angular that we
trust this. Interpolated, I get the same messageas inside the text area. Binding to the
href, that link also works. And then binding to the style, my background is red because
the content hasn't been sanitized. So this is how we go and get contentinto our UI
bypassing the security that Angular is going to put in place. It all comes down to these
type methods off of our DomSanitizer. We're going to be using these bypass security
methods. And you can see in the IntelliSense, it pops up the warning that we had
looked at. So be careful when you're using this, but it is available if you need it.

Wrap Up

The takeaways from this module are pretty easy. Angular does its best to protect us
from cross-site scripting attacks, and generally that's enough as long as we're cognizant
of the potential issues and don't do anything stupid. If we need to bypass that default
security, we can. But be careful. You may think that you're just taking in a certain type
of content, but you can't control what people will enter once you've opened that hole
in your protection.

Bringing It All Together: Building Dynamic Forms

Introduction / What We're Building

Here we are, just about the end of the course. We've covered a lot and still have one
more piece of functionality to cover, dynamically generating forms. Just for fun and
since this is the end of the course, I included a lot of the elements from the rest of the
course in this final demo. Up to this point, all of the demos we've seen have just been
pieces focused only on the thing we're currently learning, so I figured we'd end with a
large, unified demo. Here's a partial list of the Angular constructs we make use of in
this dynamic forms demo. This isn't everything we've covered in the course, but it is a
lot of it. I wanted to add in as much as I could without destroying the scenario to show
you a cohesive example with as much in it as made sense. I don't teach the elements
here, only make use of them as I'm still focused on the teaching the dynamic forms
aspects. If you're not familiar with these, they're taught earlier in the course and just
used as another example of their use here. We're going to make our way through the
dynamic form, specifically covering these topics. As I said, along the way we'll see and
use all the elements I had on the last slide and more, but we're really focused on the
forms still. We're going to see this a lot in the browser, but I wanted to give a quick
overview of the form we'll be building. As you can see, I'm not a designer, so this form
is not styled. I was far more focused on the functionality, so I only included
enough style to support the functionality. Like any form, we have fieldswith labels and
different types of controls. What you can't see here is that the fields are created and
added to the form on the fly based on the contents of a form schema file. We'll be
taking a look at that shortly. We also have validation and field hints, placeholders,
buttons tied into the validation, so if theform isn't valid, you can't submit. Introductory
and closing text, and something perhaps not that common, but here we're displaying
the results of the markup typed into Field Two. Taking a quick look at our form just in
the browser to see the functionality, you can see we have a modal loader while the
data is being retrieved from the server asynchronously. It covers up the form until the
data is loaded and then disappears and gives us access to our form. So we have text
boxes, text areas, radio buttons, checkboxes, number controls, and a drop-down. We
have some basic validation in that if we take out the value, we can see we have a
placeholder. We also have an indicator that says this is a required field. If I go ahead
and type something into this field, we have our custom validator that says this value
has to be unique, so we need to make sure that that is a unique value. We have our
hint icon that shows up here. When we go and click on that, it shows whatever the
parent container or parent component sayswe should display as a hint. In our text
area, enlarge that a little bit, we do have live sanitization going on, and we can see
over in the console window that we had some sanitization events happening. So if you
take a look at the URL for this, you can see that it has been sanitized. The JavaScript
isn't going to be injected, but we can do bold, we can do bullets, things like that. We
can change our number control. We can change our drop-down. And you'll also notice
over on the right-hand side here in the console that we have some blur and
focus events going on. If we go ahead and save this, we're just logging out to the
console. Here are all of the different values that were in our form. And like I said, it's
up to the parent component to save these back to the server. We're going to take a
look at how we delivered all of this functionality as we work through the demo in the
rest of this module.

Defining the Form in Metadata

All of the dynamic aspects of the form are driven from the field metadata, which is
based on the field base class shown here. It defines the various bits of information
about any given field to be displayed on the form, covering everything from the label
to a default value to functions for custom validation, showing a field hint, responding
to focus and blur events, and more. Depending on your requirements, you may need
to add some elements to your field definitions or change or delete some of this, and
that's fine. This is just one way of tackling the core problem. Feel free to expand upon
it. I think it shows a good sampling of what's possible. Let's go take a look at how we
put this metadata to use.Looking at how our field metadata is set up, we start with
our abstract base class, and it just defines the core pieces of information about every
field that we're going to be adding into our form. It also has some functions for
enforcing some unique validation and responding to focus and blur events, as well as
showing some information about the field in the form of a hint. You can see in the
constructor, we take in an internalName and a displayName. The internalName makes
use of an internalName class, which all it does is make sure that the internalName does
not have any spaces in it. And we do that because the internalName is used as the
control ID in the HTML, so we just want to make sure that it's valid. We also have a
base class that extends that field base for anything that contains multiple choices, like
drop-downs or checkboxes. We have an enumeration that we'll use when we're
rendering into the UI for the different types of field controls that we support. And then
we have multiple classes for different types of fields, and for now all they do is set their
displayAs. So we drop down multiple lines of text in a note field, multiple choices in
checkbox, a number field, and a single line of text. So that's what defines the metadata
for our different fields. Actually setting it up we do inside our parent component, in
this case our widget. You can see we just create instances of different types of
fields,set some properties on them, and then push them into a fields collection. So we
set up a text field, a note field, a radio button, a checkbox, a number field, and a drop-
down. And as I said, each gets pushed onto fields collection, and that's what we'll work
with when we're rendering the fields into the UI.

Generating the Field UI

Once we have the field schema created, generating the proper user interface is
relatively straightforward. Your requirements could certainly add some complexity to
this, but at its core the process is pretty simple. Iterate through the fields you've
defined and load a component for each. We do that with an ngFor used to create
instances of our field component. Inside that field component, load the appropriate
template based on the type of field to be rendered. We use a dynamic
ngTemplateOutlet instead of a big ngSwitch. And last, set properties on the
field's HTML element by binding to properties from the field schema item. There's a
little bit more to it than just this, but for a basic functional form not much. Let's go take
a look. Looking at how we generate our dynamic form, we start in our
parent component, the widget component. It declares an instance of our dynamic
form using the component attribute selector dynForm. It passes in our fields collection,
values observable,which we'll take a look at in the next demo when we're talking
about data operations, and then also a handler for the submit event. Finally, it sets up
two divs with some content, preForm and postForm.And you'll see in just a few
seconds, we're going to get that into the proper place on the form using content
projection. The class for this, what we're going to look at now, is the fact that our
frmSubmit, the show event, the focus and the blur events are all handled in the parent
widget as opposed to handled in the form or in the fields because presumably the form
code is going to be somewhat generic. It's going to be used across multiple instances,
multiple forms, whereas the parent container is what's going to have all the
logic specific to a particular use of the form. So we want to have all thelogic in the
parent container. The dynamic-form component, as I said, it's set up with a component
attribute selector. So we have the ability to put it just on a div like we did, so there's
dynForm. We have a couple of inputs to get the values in. We saw those when we
declared this in the widget component.We're going to dig into the onInit a little deeper
when we're talking about data operations, but I want to show you just line 27 where
we're setting up our FormGroup, so that's down at the bottom here. We just take the
fields collection, which is an array of FieldBase objects. We create an object that has
the information for each one and the validators set up. We'll look at the validators in a
little more detail a little bit later. And then we just set up our FormGroup based on that
object. So we now have all of the different fields set up inside this FormGroup. The
HTML for this, we're going to set up our asynchronous loader. So until the data is
actually resolved by that observable, we're going to show that loader. We saw that
when we looked at the form. Once the data is resolved, once that observable starts
returning data, then we're going to show our form itself. And you can see we're using
the content projection to get the preForm and the postForm in place using the ng-
content. We set up our submit. We'll take a look at that when we get into the code,
our form group, and then we have a div that's using an ngFor to iterate through the
fields collection. We have a custom trackBy, and then we create one of two different
types of fields, either one that has the hint functionality or one that doesn'tdepending
on whether or not we have something wired up to that hint. Below that we just have
our buttons, pretty standard form stuff there. Going down one step deeper, we can
take a look at our field.So the field itself is set up as a separate component. We're
going to get multiple instances of this created by the ngFor. It's going to show the
fieldLabel. And depending on whether or not the field that this field component is
rendering is required, it's going to set that required class using the ngClass
attribute. We then set up our form field, and we're going to use the ng-container and
ngTemplateOutlet with a dynamic getTemplate to determine which template we're
going to pull. We set up two spans for either the hint icon or the error icon, and they're
going to show depending on whether or not we have a hint to show for a particular
field and whether or not there's an error in the validation for that field. So we'll see
those in a little more detail when we get into the TypeScript file for our field in just a
moment. The rest of this file is going to be the different templates for our field
types.And this is what's going to be returned by the getTemplate function call we have
on the ngTemplateOutlet. So we have a simple text field. We have a text field that's set
up to be unique, and we'll take a look at the unique directive in just a moment when
we talk about validation. We have a text area that's going to be rendering off to the
right-hand side as saw in the demo. It actually renders out the sanitized markup that
was put into the text area. Checkbox, radiobutton, dropdown, and number.Now if you
wanted to extend this with additional field types, you would just add additional
templates here. Last, we'll take a look at the field.component class file. You can see we
have an input for the field itself, for the form. We have an output that's going to
control whether or not we display a hint and the action that gets called when a user
clicks on that hint icon. And then we're using ViewChild to go and get TemplateRefs to
each of those different templates that we just saw in the HTML. Inside the constructor,
we just pass in Renderer2 and the DomSanitizer. We're going to make use of those to
manipulate our UI and then sanitize the content coming out of that text area. In
ngOnInit, we set up the showHintLink boolean variable to be either true or false
depending on whether or not anything is listening on that hint observable. So only one
of our fields has a hint handler set up, so that's the only one that's going to get that
little hint icon. And then we go and grab the formControl coming out of the form
that represents this particular field. So how is this field shown in the UI? What form
control is doing that? After ViewInit, we go and set up our nativeElement. We're going
to use that for showing the hint and validation icons and errors messages. And we
register our listeners for any operations. In this case, we're just using focus and
blur. Here's our getTemplate that's called by the ngTemplateOutlet,and this is what's
going to control which of those HTML templates is used for this particular field
rendering. We use that displayAs, which is our enumeration. We check to see whether
or not the field is set up to be unique, and this is one of our custom validation
pieces that we'll see when we get into the validation section of the module. But if the
field is specified to be unique, that is if there'ssomething registered or something set
on the property checkUniqueFunc, then we're going to go grab the unique version of
the template. Otherwise, we're just going to grab the regular template version.And
that's what gets returned and therefore rendered into the UI inside this ng-container.
Showing the hint details, this is what gets clicked on when you click on the hint
icon. It's just going to emit to the registered hint handler. And then we come down
here and we're doing some Renderer2 work forshowing error messages or hint
messages, and they ultimately just call this showMsg, which creates a span, adds some
text to it, and then appends it onto the DOM. Hiding the message just takes it out.We'll
take a look at the validation error messages more when we get into the validation
section. And then registering our listeners. In this case, we're checking to see what
events we want to listen for. So if the field has a focus handler defines, we're going to
register a listener for the focus event. If it has a blur handler defined, we're going to
add a listener for the blur event. And you could extend this by registering any other
handlers that you wanted inside here following this same model. Each of those calls
processEvent and passes in the event that was handled. So processEvent is just a
switch that says well which one of these do I need to call? Real quick we'll take a look
at the key down here, and it's important to read that important comment that I have
at the top. This isn't a perfect implementation of parsing out dangerous content, but
it's a start. But I wanted to have something in the demo that made use of the
DomSanitizer. So here we just go through and strip out some of the HTML and then
ultimately call the bypassSecurityTrustHtml and render that value off to the right-
hand side of our Field Two of our text area. So that is everything that's involved in
getting from the field metadata to the field being rendered inside the UI. And now that
we've done that, the last couple things we need to do are just our data operations to
actually display the data, validate, and then save the data back to, ultimately, the
server when the user clicks the Submit button. We'll take a look at those next.

Loading and Saving Data

A form isn't much good without data. There are three main data operations forms
need to be concerned with. The initial load of the data or any default values, validating
the data, and saving the data. Two of these, loading and saving, are pretty
straightforward from the forms point of view. Really as far as the form is concerned, it
takes in values and displays them in field controls. Then when the user clicks the
Save button, takes the values out of the forms controls and passes them back to
whatever component contains the form. It's that owning component's responsibility to
retrieve the data from wherever it's stored, massage it as required into the format
expected by the form, and hand it to the form as part of the load process. And then do
the reverse as part of the save process. Receive the data from the form, convert it to
the format required by the storage medium, and pass it over to be stored. The form's
involvement is pretty thin for each of these. The only place the form really has to do
much work is in the validation phase. Fortunately, Angular gives us a lot to work with
there, so even that's pretty slim. We're going to take a look at all three data operations
in our demo, but we're going to start with loading and saving and then
tackle validation on its own. Taking a look at the load process for our form and how we
go about getting the values into the appropriate fields, we're going to start at the
bottom and kind of work our way out. So we're starting at the field level itself. But one
of the things that you'll notice is that we don't actually do anything with values at the
field level. We don't bind the value into a values property on any of our controls. So to
see values, we need to start by moving up a level, so we'll move up to our dynamic
form. Well the only thing the dynamic form does from a data point of view, and we can
see here in the HTML, is we have our dataObs. And that's just used to control whether
or not we're going to display the form or whether we're going to overlay that modal
loading message. So let's take a look at the code and see what happens with the
dataObs. So the dataObs is actually created on line 33, but you'll notice on line 29, it's
working within something called the valuesObs. Now we'll take a look at valuesObs is
set up, but if we scroll up here, you'll see that the valuesObs is an input that's passed
into our form. So we know that that's going to come from the parent widget
component. Once that valuesObs is complete, we're going to start working with
thevalues that are inside there. So we cast it to a promise, so we can just wait until it's
totally done, until complete has been called on that observable, and then we're going
to have a values object, which is an array of key value pairs, the key being the name of
a field and the value being the value for that field.So we set up a temporary holding
area called formValues, and then we create our dataObs. We iterate through the fields
collection for each field on our form, and we grab its value out of the values array
that was passed into us. We check to see whether or not we have a value. If we don't,
then we're going to either use the default value specified for the field, or we're going
to use a null if there's no default value specified. And this is important because
ultimately we're going to call setValue down on line 43 and pass in this formValues
object that we're creating. And setValue is going to require that every field in our form
be represented in that formValues object, so there has to be a property with the name
of the field in that formValues. So we want to make sure that we're touching every
field and setting it up on formValues. So once we've gone through every field in
the fields collection, then we make the call to setValue, pass in the formValues, and
now we're basically done setting up the values on the form.Calling setValue and
passing in that object creates a connection down to each field and sets the value for
that field based on what was passed in in formValues. So now we can call
observer.next andobserver.complete, and this closes out our dataObs. So the loader is
going to go away, and we're now going to see the form itself. We now enable the form.
It was actually disabled up on line 28, probably overkill because we have the modal
overlay sitting on top of it, but I just wanted to demonstrate how you would disable or
enable a form programmatically. So that gets the values into our fields and showing in
the UI, but we still need to look at where valuesObs came from. We know it's an input
property, so that means in the call to our dynForm, we're going to have to pass it
in. And sure enough here in our widget component HTML, we're binding valuesObs to
something called existingVals. Taking a look at the code for that, you can see
existingVals is another observable, and here's where I'm simulating getting that
data just for the sake of the demo. And I'm setting it up to show how youwould wait
for data to come back from two different sources that would come back at different
times. So the observable for existingVals has two set timeouts inside it, one that
resolves in a half a second and one that resolves in a second and a half. It's going to
make a call to a getExistingData for each one of those timeouts. Down here you can
see that the first getExistingData returns fields 1 through 4, and getExisitingData2
returns fields 5 and 6. So when we're going through the first timeout, we get our
existing data back. We're going to assign that into allVals, which is just a
temporary holding area I have set up. And then we're going to check to see whether or
not we have a value for every field. We do that by comparing the length of the
properties on allVals to the length of fields. If they're the same, then we're
done. We've gotten a value for every field, so we can complete. Now in this first case,
they're not going to be because we only got fields 1 through 4. Coming down and
taking a look at the second timeout, we're going to do the same thing, and we're going
to compare the length of allVals, the properties on allVals, to the length of fields. This
time they're going to be the same, they're going to match, because we've gotten the
last two fields. So now we call observer.complete. And observer.complete is going to
fulfill the promise that we're waiting for back here. So now we've seen the process of
getting data from our parent component, which is essentially controlling things, and
this is what's going to work against the server to retrieve the data and pass it all the
way down to the form and ultimately display it inside the fields in the appropriate
places. Going the opposite way saving the data, when the user clicks the Submit button
on our form, we have our ngSubmit event bound to this frmSubmit. FrmSubmit is set
up inside our component file here. We're going to check to see whether or not we
have a submit handler registered, and we'll take a look at where the submit handler
comes in. Then we just need to do a little bit of manipulation to hand the data back
with the appropriate name because we had switched the internal name to make sure
there were no spaces when it came into the form. So now going out, we want to make
sure that the spaces are put back in. We do that just by referencing the original name
value on the internalName object, and then we're going to call that submit handler and
pass in the object that we just created with key value pairs of the original name and
then the value coming out of the field control. The submit handler is an input property
specified on our component. So we take a look at where the component is
instantiated, and we can see that we're binding submitHandler onto something called
frmSubmit. So we take a look at frmSubmit, and we can see all that's doing is writing
the values out into the console as we saw in the first demo where we click on the
frmSubmit button and then the values are just written to the console. This is where it
happens. And the important thing here is that the functionality for that is handled
inside this parent component. The parent component is responsible for connecting to
the database, both for loading the data, as well as saving the data back. The form just
says here's the data that was in the fields. You do whatever you need with them. It's
up to this specific parent component to determine what that is.

Validating the Field Data

Angular gives us a lot to work with for doing data validation, but we're only going to
quick touch upon that core validation functionality. We're going to focus on the UI and
dynamic aspects that are different in a dynamic form as opposed to just a simple static
form. If you're not familiar with Angular's validation functionality, don't worry. It's
pretty straightforward, and you should be able to pick up whatyou need as we go. Plus
we'll be using both out-of-the-box and custom validation, so you'll see examples of
everything you need in the demo. Validation in general typically comes down to
verifying one or more things about a piece of data. The first and easiest is
simply verifying that you actually have a value when one's required. Next is validating
that the data value is in a range, which can beeither fixed or dynamic. This includes
checks like between X and Y, less than X, greater than Y, something like that. This is
fairly broad and covers string, number, and date values, but when you boil all of it
down, it's just range checking. Equality, simply checking that a value equals or does not
equal some other value. Membership, whether a value contains another value or is
contained in some other collection. Pattern matching, typically things like
email addresses, URLs, phone numbers, etc. You simply need to check whether your
value follows a certain pattern. And then the catchall, custom validation. This covers
anything you need not covered by one of the above. From these general types out of
the box, Angular gives us exists in the form of a required validator, range with
validators for min, max, minLength, and maxLength, equality in the form of a
specific requiredTrue validator, as well as the ability to check equality using a regular
expression pattern, patterns using that same regularexpression validator, as well as
one specifically for emails, and finally the ability to write our own custom validators. So
the only generic validation scenario Angular doesn't support out of the box is
membership. That's not too bad. That's not to say that you'll never need to write a
custom validator for any other type of validation, just that Angular's at least able
to check the box for most of the common validation scenarios. In the demo, we'll use
the required validator, as well as a custom validator, so let's go take a look. Starting
with the out-of-the-box required validator, when we set up our form group as part of
the field schema, you remember we iterated through the fields collection and created
form controls for each of the fields. And we checked to see whether or not the field
was required because if it was, we set the form control up with the required
validator. So that's essentially all we need to do to make use of the out-of-the- box
validators is just make sure that they're included in the FormControl declaration when
we're setting up our form group. Rendering that into the UI, we have a couple of
different aspects to it. We're going to start with the label for our field. We're going to
use ngClass to dynamically apply the required class if the field is required. The required
class uses the afterpseudoselector to just add a red asterisk after the label. Back in the
HTML, we also have a span set up to show an error message. That's that little red circle
with a white exclamation point in the middle.That's only going to show up if the
showError property is true. In our TypeScript file, showError is set up to return, first to
check and see whether we have a form control and the form control has beentouched
because we don't want to show the error if the user hasn't been given the chance to
put any value into the field. So if we have a formControl, the user's clicked into and
clicked out of the field, and the field is now not valid, then showError is going to be
true, and that's going to cause our icon to show up. Now the forms can be marked as
invalid if it fails validation, so so far we've just set up the required validator. If the
required validator fails that field value, our formControl will be marked invalid.
ShowError will now be true. So that takes care of the out-of-the-box validation. Now
let's take a look at our custom validation to check value uniqueness. Our unique
validators can be set up a slightly different way to show another way that we can go
about achieving the same validation results. So if you recall when we were setting up
our form schema, when we set up Field One, we attached the checkUnique function to
the checkUniqueFunc property of the field. The checkUnique function justreturns true
or false. If it's 1, 2, 3, 4, 5, it returns false. Otherwise, it returns true. That's what's
going to be called to validate the value in the field, and it's important again to see
that this is declared inside the parent component because this allows our form and our
validation in the form to be relatively dumb. It doesn't need to worry about how to
validate uniqueness. It just needs to know it needs to call this function, so that
allows the form and the fields to be generic. So once we've set up a property value for
checkUniqueFunc, when we're rendering the field into the UI, it calls this getTemplate.
It's going to check to see whether or not that checkUniqueFunc has a value. If it does,
it's going to go try to grab the unique template. The unique template is declared inside
our HTML right alongside the non-unique version, and the only difference is that it has
this unique directive applied to it. The unique directive is just a standard directive
except that we've put the validation functionality in here. So we provide our unique
value directive. We need to implement the validator interface. The validator interface
is going to require that we implement these two functions down at the bottom here,
validate and registerOnValidatorChange. Nothing we need to do in the second one, but
the first one, validate, is what's going to get called when Angular is going to check the
value of this field to see whether or not it's valid. So this is where we go back to the
checkUniqueFunc property on our target field, pass in the field value, and get back a
Boolean true or false. If we get back a true, we're just going to return an empty
object. If we get back a false, we're going to return from the validation check this
object with the name of our validation that failed as the key, notUnique, and then a
value of true. That's going to allow us to present in the UI a message that says here's
the validation that failed. Taking a look at this inside the UI in our browser, we have
our validation set up on Field One. So if I take this value out and click out of the field so
it's now registered as touch, we see our little error indicator show up. If I run my
mouse over that, it says the field is required. That's the validator that failed. If I go back
in and start putting in a value, that message disappears because I now have a value in
there until I hit the value that my unique validator is going to return false for. At this
point, it says the value must be unique, so that validator has failed. If I go back in and
change the value to something that is okay, now the unique validator disappears. How
we got that validation message is going to be back here. Now when we run our mouse
over that error icon, it's calling this showErrMsg function, which calls into the showMsg
function. We can see, in order to get the text for that message, it makes a call into
getValidationErrMessage. GetValidationErrMessage checks the errors property of our
formControl, so for this particular field, and builds the string based on which validation
failed. That gets returned and displayed inside that little pop-up balloon that says what
the error message is. So that's kind of soup to nuts how we go about registering
validation, either out of the box or custom, and then updating the UI to show the user
whether or not their values are valid.

Wrap Up

So that's dynamic forms. Once you dig into it, it's really not too bad. Certainly your
requirements could make things complicated, but at its core, there's nothing
particularly difficult about it once you've seenhow it all works. To me the most difficult
part is defining the metadata properly, and that's not very hard once you've done it a
few times. The rest is more or less boilerplate from there on out. You could use the
same field components and templates over and over again and just change out the
metadata and the parent template where all of your event handlers are defined.

Wrap up: Use Cases and Final Thoughts

Introduction

We've covered a lot of material in the last couple of hours, but one thing we haven't
really touched upon is specific use cases. I've mentioned some as scenarios for the
demos, but was more focused on the concepts and the technology than when it makes
sense to use it. I'm going to remedy that now by spending just a little bit of time talking
about what we've learned and where it can be used. I'm going to focus on three
specific areas for use cases. Not because these are the only applicable scenarios, but
simply because I think they're the most interesting and the places where we can really
get some great value out of what we've learned. The three areas I'm going to focus on
error handing, personalization,and, kind of a catchall, general UI goodness, things that
can really make your user interface pop. Also, while some of what we've covered in
this course can certainly be used in non-UI parts of yourapplication, we're focused on
the UI. Except for a little bit of cheating in the error handling section, I'm going to stick
with a UI focus for these discussions. Finally, if you remember back in the very first
module when I was introducing the course, I mentioned that this course was perhaps
a little different from other courses you may have come across. I'm as interested in you
leaving the course with questions as with answers. By that I mean I want the material
presented here to make you think. I want you to learn concepts, as well as syntax, and
walk away from the course thinking about where else you can use the material you
learned here. To that end, the scenarios I present in the rest of this module arenot
anywhere close to an exhaustive list. Think of them as a starting point, rather than an
end. I want these to spark your imagination to come up with your own uses for the
material we covered. Let's go.

Error Handling Scenarios

At a very high level, error handing is two things, logging the details of the error and
showing a nice, friendly error message to the user, one that ideally makes them feel
like they didn't do anything wrong,even if they did, and gives them some pointers on
what they can do to fix the problem. So what parts of what we covered in this
course could come into play? How about an easy one. We already looked at using an
output decorator to show or hide a link to the help desk if the application supported
it. If the app doesn't, we don't show the link. Now that's kind of nice. How about a nice
error message for the user to let them know that we're collecting some information
and submitting the error details in the background and to please wait. The async
loader UI we looked at could help with that. Templates and templateRefs to show a
consistent UI to a user when something goes wrong, something defined once and used
wherever we need it. Or taking that one step further, maybe that's a dynamically
createderror component that handles the data collection and reporting while showing
a nice, consistent message to the user. Or maybe every component in our app inherits
from a single base component where all of the error handling logic is centralized. Or
another easy one. We saw directives in simple UI elements to use when validation has
failed, so maybe that's another piece that we can use for error handling. Now I said I
was going to cheat a little in the error handing section, so here you go. This is both new
and not really UI-related, but it's an adaptation of something we talked about already
and anexample of the type of creative thinking I want to encourage you to do. How
about a TypeScript decorator like the one we saw for memoizing that rewrites
functions to be NoOps when running in production mode. This allows you to put a
function in your code that will become a NoOp in production, and call it almost as
much as you want with effectively no impact on performance. On an average dev
box, 1,000 calls to a NoOp function, like the 1 created by this decorator, consume less
than 1/2 a ms of time. At that level, there'ss no reason to remove this function or the
calls to it from your code before deploying. Or take that even one step further and
have a whole set of logging levels to control what gets logged in conjunction with
another decorator.

Personalization Scenarios

In a sense, personalization is the art of making a user feel like you created a site or
application just for them, even if they're just one of thousands of users. Certainly the
aspects of a dynamic UI that wespoke about can come into play here, but what are
some specific cases? We could easily set up a template to display personalized content
or controls, present it via an ngTemplate outlet, and personalize the display by setting
values in a dynamically generated ngTemplateOutletContext.Dynamic components,
along the line of what we saw with the widget framework, can be used to allow users
to personalize the information presented on the screen when they're using your
application. Or directives to control theming, content, and other aspects of the UI to
user-configurable settings. And last, maybe allowing users to customize some aspect of
your application's forms to fit the way they fill in the details, something as simple as
reordering the fields or setting their own customized defaults.

UI Goodness Scenarios

Finally, just about anything you can do to make your user interface pop is probably
going to be a good thing. Users may not even realize why, but they'll just like your
application better than one that doesn't pay attention to some of this detail. So things
like maybe using pipes or ngPlural, which we didn't cover, but it's easy so you can go
look it up to avoid that ridiculous S in parenthesis just in case its plural silliness in your
UI. Or any of the things we talked about on the performance module to justmake the
application as fast as it can be, especially perhaps the bit about impure pipes and their
almost guaranteed impact on performance if you're not careful. HostBinding and
HostListening to make the UI as responsive to user actions as you can. The benefit of
these is how easy they are, so it doesn't take long to include all this
interactivity. Similarly, using ElementRef, nativeElement, and Renderer2 to
improve interactivity, but also paying attention to the performance things we already
talked about to make sure that performance doesn't suffer because of it. Use the async
loading UI elements we talked about to let users know when things are happening in
the background, so they don't think the application is frozen or unresponsive. It
doesn't have to be a blocking loading message or modal like we demonstrated, maybe
something as simple as just a message and a status bar. The more users know about
what's going on, the more comfortable they'll be with your application. And last,
something your users will hopefully never see or have to deal with, but perhaps the
biggest thing you can do to improve their satisfaction, is making sure that they never
have to worry about their personal information being compromised because of a
successful XSS attack on your site or application. So that's it. I hope you've gotten a lot
of great stuff out of this course. Now go out there and create some awesomeness.

You might also like