- 1 Introduction
- 2 First Things First
- 3 Introduction to Components
- 4 Templates, Interpolation, and Directives
- 5 Data Binding & Pipes
- 6 More on Components
- 7 Building Nested Components
- 8 Services and Dependency Injection
- 9 Retrieving Data Using HTTP
- 10 Navigation and Routing Basics
- 11 Navigation and Routing Additional Techniques
- 12 Angular Modules
- 13 Building, Testing, and Deploying with the CLI
- 14 Final Words
This beginner level course takes you on a journey through the basicfeatures of Angular. It guides you down the right path, making yourown journey with Angular more pleasant productive.Along the way we build a sample application so you can code along oruse it as a reference for your own development.You’ll see how Angular provides a consistent set of patterns forbuilding components, templates, modules, and services, helping youcome up to speed quickly.This course covers how to build components, how to create the userinterface for your application in a template, and power it up withdata binding and directives.
You’ll discover how to build services for logic needed acrosscomponents and inject those services where they are needed.You’ll learn how to send requests to a web server using HTTP andobservables, and you’ll see how to set up routing to navigate betweenthe views of your application.In addition, you’ll see how to use the Angular command line interfaceor CLI to generate, execute, test, and deploy your Angular application.By the end of this course you will know the basics you need to getstarted your own Angular applications.I hope you’ll join me on this journey through Angular:
You’ll see these productivity improvements as we go through thiscourse and we’ll discern a consistency of patterns for building theblocks that form an Angular application.Int his first module we lay out the anatomy of an Angular application.We consider several suggestions for getting the most from this course.We explore the sample application that we’ll build throughout thiscourse, and we’ll look at the topics we’ll cover in the remainder ofthis course. Now let’s check out the anatomy of an Angular application.
Anatomy of an Angular Application
In Angular an application is comprised of a set of components andservices that provide functionality across those components.So what is an Angular component?Each component is comprised of a template which is the HTML for theuser interface fragment defining a view for the application.Add to that a class for the code associated with the view.The class contains the properties or data elements available for usein the view and methods, which perform actions for the view such asresponding to a button click. A component also has metadata, whichprovides additional information about the component to Angular.It is this metadata that identifies the class as an Angular component.
So a component is a view defined with a template, its associated codedefined with a class, and additional information, defined with metadata.We’ll look at this in more detail in the upcoming modules.As we build these components, how do we pull them together into an application?We define Angular modules. Angular modules help us organize ourapplication into cohesive blocks of functionality.Every Angular application has at least one Angular module called theapplication’s root Angular module.An application can have any number of additional Angular modulesincluding feature modules that consolidate the components for aspecific application feature. We’ll see much more about Angularmodules along our journey. For now let’s look at some tips forgetting the most from this course.
Get the Most from This Course
This post lists common issues along with their solutions.If you are having problems with the code for the course, check here first.There may already be a solution posted.Keep this URL handy as you work through the course.When building web applications regardless of the technologies we use,there are often lots of steps and places where things can go wrong.That’s where a good checklist can come in.I’ll present checklists at the end of each module and we’ll use themas a brief review of what was covered in that module.Feel free to jump ahead to the checklist if you have any problems whencoding along with the demos in the module and consider referencingthese checklists as you start building your own Angular applications.
Coding along on this journey is another great way to get the most fromthis course. Though not required, it is often helpful to try out thepresented code as you navigate through the course.To get you started, I’ve set up a public GitHub repositoryspecifically for this course. It is called Angular: Getting Startedand you can find it at this URL.The starter files for the sample application are here.You can use these files as a starting point if you want to code alongwith the demos. If you’d prefer to follow along with the completedcode, you can find that here. If you’re new to GitHub, simply clickthis button to download all of this code as a zip file.So what is this sample application? Let’s take a look.
To demonstrate the basic features of Angular we’ll build a simpleapplication step by step as we journey through this course.Let’s see the finished sample application in action.Welcome to Acme Product Management.As its name implies, this application manages our current list of products.Here at the top is our menu for access to the key features of the application.In a full-featured application there would of course be more optionshere, but we want to limit this sample application to the features wecan build within this course.
Clicking on the product list option displays the product list page.We see the page title and a table containing the list of products.If the user clicks the Show Image button, the product images appearand the button changes to hide image.Click the button again to hide the images and compress the display.Notice the nice formatting of our price and instead of a number forthe rating, we display the rating in stars.Here at the top is an input box where the user can enter a filter string.When the input box contains a value, a Filtered by message appears andthe product list is filtered to only those with a product name thatcontains the entered string. Click on a product name to navigate tothe product details.
On the product detail page we see the page titlewith the name of the product and all of the product details includinga product description, the nicely formatted price, and the star rating.Click the back button to navigate back to the product list page.So not a huge app, but big enough to demonstrate the basics of Angular.As with any Angular application, this application is comprised of aset of components including a nested component for the rating stars.It has a service to get the data and it incorporates routing tonavigate between the pages. Now that we’ve seen the sampleapplication, how do we build it?As stated earlier, an Angular application is comprised of a set ofcomponents and services that provide data and logic across those components.With that in mind, let’s break the sample application into componentsand services.
For the welcome page we’ll build a welcome component.For the product list page, we’ll build a product list component.Recall that we had a nice visual display of stars for our ratings.We want to reuse that feature so we’ll build a separate nestable star component.Clicking on a product in the product list page displayed the product detail.We’ll build a component for that as well and reuse the star component.Then we need an app component that ties our application pieces together.And our application gets data so we’ll want a product data service.Lastly, we need the obligatory index.html file.We’ll build the basics of each of these pieces and learn how toorganize them into Angular modules as we journey through this course.
We start with first things first.We’ll select a language and editor to use, then walk through how toset up an Angular application.Next we’ll dive into components. We’ll build the app component usinga simple template and minimal component code and metadata.We’ll see how to build the user interface for our application usingtemplates, interpolation, and directives.We’ll power up that user interface with data binding and nicely formatour data with pipes. Next we’ll tackle some additional component techniques.
We’ll define interfaces, encapsulate styles, and leverage life cyclehooks to build better components.We’ll see how to build a component designed to be nested within othercomponents and how to communicate between the nested component and its container.We often have logic or data that is needed across components.We’ll learn how to build services specifically for this purpose anduse dependency injection to inject those services into the componentsthat need them. Most web applications need to communicate with abackend server to get or post data and to execute back-end business logic.In this module we’ll leverage HTTP to retrieve the data for our application.Our sample application displays multiple views.
We’ll see how to set up routing to navigate between those views.Next is Angular modules. We learn about and use the root Angularmodule throughout this course, but as the application grows, we wantto separate its concerns. This course module reviews the basics ofAngular modules and refactors our application into logical blocksusing multiple Angular modules.Through the majority of this course we create our components and othercode manually, but spoiler alert! There is an easier way.We’ll learn how to use the Angular CLI to build, test, and deploy our application.We’re covering a lot of territory and by the end of our journey we’llhave a simple, but fully operational Angular application.You can use that application as a reference for your own development.Let’s start our journey through Angular.
First Things First
First things first. Before we can start coding with Angular, thereare some preparatory steps. Welcome back to Angular: in this module we setup what we need to work with Angular.A little preparation goes a long way toward a successful adventure.Before we take that first step on our journey with Angular we need tomake some decisions, gather our tools, and get everything ready.In this module we’ll evaluate several languages we could use to buildan Angular application and select one.
Once we’ve picked a language, we select an editor that fully supportsdevelopment in that language. Then we set up the boilerplate code foran Angular application, and we’ll talk about modules and what theymean in Angular. Let’s get started.
Selecting a Language
Selecting an Editor
There are many editors that fully support TypeScript either out of thebox or with a plugin including all of these.Select one of these or whichever editor suits you best, but keep inmind that your experience with TypeScript will be much morepleasurable if you select an editor that understands TypeScript.For this course, I am using Visual Studio Code.Visual Studio Code runs in Linux, Windows, and OSX.It has great features that support TypeScript such as auto completion,IntelliSense, syntax checking, and refactorings.If you want to use Visual Studio Code as your editor, you can downloadand install it from this URL.If you are interested in using Visual Studio Code and want to learnmore, check out their website or this Programfault course, but you arefree to use whichever editor you choose.Now that we’ve picked a language and selected and installed an editor,let’s set up our environment.
Setting up Our Environment
Setting up an Angular Application
Depending on the tools you select, setting up an Angular applicationcould be somewhat laborious. Before we begin, let’s list the required steps.Then we’ll look at ways to set up Angular without actually performingthese steps. To manually set up an Angular application we’d need tocreate an application folder, add package definition and configurationfiles, install the packages, create the application’s root angularmodule because every Angular application needs at least one Angularmodule, then create the main.ts file to load that Angular module andcreate the host web page, normally index.html.Luckily, we have some options. We could manually perform each ofthese steps, though it would be time consuming and prone to error sothis option is not recommended. Instead we can simply download theresult of these steps from GitHub.The Angular team has provided a set of quickstart files you can use asboilerplate code for your application.Alternatively we could use tooling such as the Angular CLI.The Angular CLI is the command line tool for generating the setupfiles and boilerplate code for an Angular application.The CLI also generates your components, modules, services, and other files.It scaffolds and executes your unit and end-to-end tests and providesoptions to minimize, package, and prepare the files you need for deployment.The Angular CLI can be found here. The CLI is the recommended toolfor building, testing, and deploying Angular applications.We’ll look more at the CLI later in this course.However, to code along with this course, I recommend that you insteaddownload the sample application starter files.These files are available in my GitHub repository.I used the Angular CLI to create these files, but then included someextra files we’ll need as we build our sample application throughoutthis course. Let’s go with this last option.I’ve navigated to my GitHub repository following the URL from the slide.If you are comfortable with Git, you can clone this repository.Otherwise click this button to download all of the files as a singlezip file. The APM Final folder contains the completed code for oursample application. Use these files if you want to see the end result.The APM Start folder contains the starter files.These are the files we will use as the starting point for building ourAngular application. After downloading the files, copy or extract thefiles in the APM Start folder to a working directory called just APM.Your APM folder should then look like this.Now let’s open the APM folder with a code editor.
Installing an Angular Application
I’ve opened the APM working folder with Visual Studio Code.First, let’s talk about the directory structure.By convention, all of our source files are under a folder called SRC.Under that folder is an app folder that contains the source filesspecific for our application. We only have a few folders and fileshere now, but we’ll add more as we progress through this course.For applications of any size we’ll have subfolders under the appfolder for each major feature in the application.The other files here are configuration and setup files, often calledboilerplate files. To get us going quickly, we won’t dive into all ofthese files now. We’ll learn more about them in the building,testing, and deploying with the CLI module later in this course.Before we can execute this code, we need to install of the librariesrequired to develop and run our application.Where are those defined? In the package.json file here.This file contains a list of all of the application’s dependencies.The @angular entries are Angular system libraries.Notice I have also included Bootstrap in this list.We’ll use Bootstrap in the sample application to make it look nice.Down here are some additional dependencies that are only required for development.This is where TypeScript is defined.Toward the top of this file is a set of scripts.We can execute these scripts using npm.We’ll learn more about these scripts throughout this course.For now, let’s install all of these libraries.First, open a command prompt or terminal.VS Code has an integrated terminal we can use.View, Integrated Terminal.Next, navigate to the folder containing the package.json file.VS Code did that for us. Then type npm install.This installs all of the dependencies defined in the package.jsonfile along with any of their dependencies.Note that you may see some warnings and messages during thisinstallation process, like these. In most cases, you can ignore them.If you see something like this tree structure at the end, theinstallation completed successfully.Notice that we now have a node modules folder here.This is where npm installed all of our libraries.This folder is large so you may want to exclude it when you checkyour files into a source control system.Now that we have everything installed, let’s try running the sample application.
Running an Angular Application
I’ve included enough additional code with the starter files to run thesample application so let’s give it a try.Remember the scripts area in our package.json file?Here is the start script. When we type npm start, it will execute thecommand defined here. The ng executes the Angular CLI.The string after the ng is the CLI command.The serve command builds the application and starts a web server.The -o is a command option that opens the URL in our default browser.The CLI has many more commands and options; we’ll see more of them aswe progress through this course.Are we ready to make it go? Let’s try out this start script.Back at the command prompt or terminal, type npm start.This executes the start script, builds the application, starts a webserver, and opens the URL in the default browser, which in my case is Chrome.If all is well, the application appears in the browser and displayssome text as shown here. If the text does not appear or you seeerrors in the console, ensure that you ran npm install successfullyas defined in the prior clip.As you can see, our application doesn’t look like much, but we’ll fixthat on our journey through Angular.I’ve moved the windows around so that we could see the editor, thebrowser, and the terminal window. Let’s see what happens when we makea code change. In the editor, open the app.component.html file.Don’t worry too much about the syntax here yet; we’ll talk about it shortly.For now we’ll just change the welcome text.We immediately see here that our code is recompiled, the browserrefreshes, and our updated text appears so any time we make a changeto our application, we’ll be able to immediately see the effect ofthat change. That will be helpful.You may have noticed that I didn’t save the file after I made the code change.When using VS Code we can set it to automatically save our changes.Here under file, preferences, settings, workspace settings, I have itset to automatically save after a short delay.When we are finished working with our files, we can close the browser,but the server keeps running. To stop it, go back to the commandprompt or terminal and press Ctrl + C or Command + C and y for yes.Then you can exit. Any time you want to run the application and keepit running to watch the effect of your code changes, simply open theterminal and use npm start again.So now we know how to build and run our code. Yay!Before we go any further, let’s take a moment and talk about modules.
In this module we discussed several languages and selected TypeScript.TypeScript has all of the productivity features of ES 2015 plus strongtyping for better tooling.We then selected an editor. Which editor you use for TypeScript is apersonal preference. For the best experience, be sure your selectededitor fully supports TypeScript.We then installed npm and looked at the laborious process required tomanually set up the boilerplate code for an Angular application.Instead of manually setting this up, we downloaded the starter filesfrom my GitHub repository. We then saw how to install, run, and editthe sample application. We covered ES modules and how TypeScript usesES module syntax to export and import functionality from our ES modules.We introduced Angular modules and how they organize our applicationand promote application boundaries.Recall the architecture for the sample application that we arebuilding that we outlined in the first module?Since I used the Angular CLI to create the starter files, it createdthe index.html file and our root app component.In the next module we’ll examine these files and start writing some Angular code.
Introduction to Components
In the last module we set up the infrastructure of our Angular application.Now we are ready to build our first component.Welcome back to Angular: in this module we walk through buildinga very basic component with a focus on clearly defining thecomponent’s parts, their meaning, and their purpose.We can think of our Angular application as a set of components.We create each component, then arrange them to form our application.If all goes well, those components work together in harmony to providethe user with a great experience.In this module we take a closer look at what an Angular component isand examine the code we need to build one.We walk through how to create the component’s class and how and whywe need to define metadata. We look at how to import what we needfrom external modules and we discover how to Bootstrap the appcomponent to bring our application to life.We’ll continue to add to this application throughout this course.Looking again at our application architecture that we defined in thefirst module, the Angular CLI created the index.html file and the app component.In this module we’ll rebuild this app component. Let’s get started.
What Is a Component?
An Angular component includes a template which lays out the userinterface fragment defining a view for the application.It is created with HTML and defines what is rendered on the page.We use Angular binding and directives in the HTML to power up the view.We’ll cover binding and directives in a later module.Add to that a class for the code associated with the view.The class is created with TypeScript.The class contains the properties or data elements available for usein the view. For example, if we want to display a title in the view,we define a class property for that title.The class also contains methods, which are the functions for the logicneeded by the view. For example, if we want to show and hide an imagewe’d write the logic in a class method.A component also has metadata, which provides additional informationabout the component to Angular. It is this metadata that defines thisclass as an Angular component. The metadata is defined with a decorator.A decorator is a function that adds metadata to a class, its members,or its method arguments. So a component is a view defined in atemplate, its associated code defined with a class, and metadatadefined with a decorator. Want to see what a component looks like in TypeScript?Here is a simple component. It might look complex at first so let’sbreak this component into chunks, starting at the bottom.Here is our class. It defines the properties and methods needed byour view. Here is the component decorator that defines the metadata.The metadata includes the template that lays out the view managed bythis component. And here we import the members that we need.Let’s examine each of these chunks in more detail, starting at thebottom with the class.
Creating the Component Class
If you have done any object-oriented programming in languages such asC#, VB.NET, Java, or C++, this code should look familiar.A class is a construct that allows us to create a type with propertiesthat define the data elements and methods that provide functionality.We define a class using the class keyword followed by the class name.A common Angular convention is to name each component class with thefeature name, then append the word component as the suffix.Also by convention, the root component for an application is calledAppComponent as shown here. This class name is used as the componentname when the component is referenced in code.The export keyword here at the front exports this class, therebymaking it available for use by other components of the application.And as we learned in the last course module, since this file exportssomething, this file is now an ES module.Within the body of the class are the properties and methods.In this example, we only have one property and no methods.A property defines a data element associated with a class.We start with the property name which by convention is a noundescribing the data element and it is in CamelCase whereby the firstletter of the name is lowercase. In this example it is the title ofthe page. Using TypeScript’s strong tying, we follow the propertyname with a colon and its data type.In this example, the page title property is a string.We can optionally assign a default value to the property as shown inthis example. Methods are normally defined within the class bodyafter all of the properties. Method names are often verbs thatdescribe the action the method performs.Method names are also in CamelCase whereby the first letter of thename is lowercase. So that’s it for the class, but a class alone isnot enough to define a component. We need to define the templateassociated with this component class.How do we provide this extra information to Angular?With metadata. Let’s look at that next.
Defining the Metadata with a Decorator
Importing What We Need
Before we can use an external function or class, we need to definewhere to find it. We do that with an import statement.The import statement is part of ES 2015 and implemented in TypeScript.It is conceptually similar to the import statement in Java or the C#using statement. The import statement allows us to use exportedmembers from external modules. Remember how we just exported ourclass using the export keyword? That means that other modules in ourapplication can import our exported class if needed.We’ll use the import statement throughout our code to import anythird-party library, any of our own modules, or from Angular itself.We can import from Angular because Angular is modular.It is a collection of library modules.Each library is itself a module made up of several related feature modules.When we need something from Angular, we import it from an Angularlibrary module just like we import from any other external module.Use this link if you want to view the list of available Angularlibrary packages and their current versions.In our component code we use the component decorator function fromAngular to define our class as a component.We need to tell Angular where to find this function so we add animport statement and import component from Angular Core like this.We start with the import keyword.We identify the name of the member we need within curly braces.In this case we need the component decorator function and we definethe path to the module containing that member.In this case the Angular Core library module.If we need multiple members from the same module, we can list them allin the imports list separated by commas.We’ll see examples of that later in this course.So this is a component. Now we’re ready to build the first componentfor our sample application. Let’s jump in.
Demo: Creating the App Component
In this demo we build our app component, which is the root componentfor our application.Here we are in the editor with the APM folder open.This is the folder we set up in the last module from the starter filesI provided. Let’s open the src folder and under that, the app folder.Since I used the Angular CLI to create the starter files, it createdthe root app component. It named the file app.component.ts.The file naming convention that we’ll follow throughout this course isto start with the feature name.This is our root application component so by convention it’s calledapp, then a dot, then the type of ES module defined in this file,in this case, component to identify this ES module as a component,another dot, and the extension.Since we are using TypeScript, we’ll use ts as the extension.Let’s open that file. In VS Code I can click the Explorer icon toclose the explorer and see more of the code.I can reopen the Explorer by clicking the icon again.Now I’ll delete the starter code for this file so we can build the appcomponent from scratch. I like to start coding by building the class,but the order of these steps really doesn’t matter.When we build a class, we first type in the export keyword to ensurethat other parts of the application can use this class.Next we type in the class keyword, then the name of the class.Since this is our application component class, we’ll followconventions and name it AppComponent.Inside this class we’ll define one property, the page title.We type the property name followed by a colon and the property datatype, which for the page title is a string.Notice how IntelliSense helps us here.For this property we want to define a default value for the page title.Next we define the component decorator above the class.The component decorator always begins with an @ sign, then the name ofthe decorator and we’re using the component decorator.The component decorator is a function so we type parentheses and we’regoing to pass in an object so we type in curly braces.Notice how TypeScript has underlined the component decorator andflagged it as an error. The error is, cannot find name component.Any guesses on what the problem is?If you said that we are missing the import statement, you are right.We need to import the component decorator from Angular Core.Now the error underline goes away and we can complete the metadata.In the component metadata we specify a selector for the name of thiscomponent when used as a directive in the HTML.Now that we’ve imported the appropriate module, we get IntelliSensefor these properties. We set the selector to pm-root.The current convention is to prefix each selector with something toidentify it as part of our application so we selected pm for product management.We end with a name that represents this component so we used rootsince this is our root app component.We’ll see how to identify our desired selector prefix to the AngularCLI in the Building, Testing, and Deploying with the CLI module laterin this course. Next we define the template.To specify another property here we enter a comma and then the name ofthe other property. We want to define the template.Any valid HTML can be specified in the template.We’ll dive deeper into templates in a later module.So for this example, I’ll just paste in the HTML and we’re done.We have now created the first component for our application, yay!But how do we use it? How do we display its template?
Bootstrapping Our App Component
You may have heard the saying, pulling yourself up by your bootstraps,originally meaning to improve your situation by your own efforts.In tech it has come to mean a self-starting process that loads and goes.We need to tell Angular to load our root component through a processthat is called Bootstrapping.We first set up the index.html file to host our application.Then we define our root Angular module to Bootstrap our root component.Let’s look at both of these steps.Most Angular applications have an index.html file that contains themain page for the application.This index.html file is often the one true web page of the application.Hence an application is often called a single-page application orSPA, but don’t worry. It will look to the user like we have lots ofpages as we saw in the demo at the beginning of this course.What we do is insert bits of HTML into the one HTML page defined inindex.html. Let’s see how that works.Here again is our app component just shifted to the right.Recall that the selector is the name of the component when we use itas a directive in HTML and the template defines the HTML that we wantto display. So in the index.html file we simply add the selectorwhere we want our template displayed.Here in the template we call this a directive.A directive is basically a custom element.As soon as the loading is complete, the HTML defined in the componenttemplate is inserted between the selector element tags and appears onthe page, but how does the Angular compiler know about this customHTML element?It looks in an Angular module. Angular modules help us organize ourapplication into cohesive blocks of functionality and provideboundaries within our application. They also provide a templateresolution environment. What does that mean?When the Angular compiler sees a directive in a template, it looks tothe Angular module for the definition so we declare the AppComponentin an Angular module so the compiler can find it.We also use the module to Bootstrap our startup component, which isour AppComponent and we want our application to work correctly in thebrowser so we add Angular’s browser module to our Angular module’s imports.Okay, pictures are nice, but what does that look like in code?Here is our application’s root Angular module.As with most everything in Angular we define an Angular module usinga class. We identify the class as an Angular module by attaching theNgModule decorator and passing in metadata defining the details ofthis Angular module. For the NgModule decorator, the properties are arrays.In the declarations array we define which of our components belong tothis module. By convention, our root application component,AppComponent, belongs to the application’s root Angular module,AppModule, so we declare it here.We can add other components here as well.We’ll cover best practices for organizing our application into Angularmodules later in this course. For now, all of our components will bedeclared here. In the imports array we define the external modulesthat we want to have available to all of the components that belongto this Angular module. External modules could be modules provided byAngular, a third party, or our own Angular modules.Here we import browser module, which every browser application must import.Browser module register is important to application service providerssuch as error handling. The Bootstrap array defines the startupcomponent of the application, which is our AppComponent.The startup component should contain the selector we use in theindex.html file, which in this case it does.Now let’s check it out in this sample application.
Demo: Bootstrapping Our App Component
In this demo we’ll set up index.html to host our application andexamine the root Angular module that Bootstraps our AppComponent.Here we are back with our sample application exactly how we left it.Since I used the Angular CLI to create these starter files,the index.html file is already hosting our app component and theapp.module.ts file already Bootstraps our app component.Let’s take a look starting with the index.html file.To host our application we use the component selector as a directivehere within the body element. We can think of a directive as simplya custom HTML tag. Since I used the Angular CLI to create the starterfiles, the directive is already included here.Now let’s open the app.module.ts file.Here is the class and here is the NgModule decorator defining thisclass as an Angular module. The declarations array declares theAppComponent so that Angular can locate its selector.The imports array includes BrowserModule so the application runscorrectly in the browser. The providers array is for services.We’ll talk more about those later in this course so it’s empty hereand the Bootstrap array lists our AppComponent as the startingcomponent for our application. It looks like we are ready to run.We saw in the last module how to start the application by typing npmstart in a terminal or command window.When the root app component is loaded, the HTML from our componentappears and the binding in that HTML is replaced with the value of ourpage title property. We now have a working, albeit very small, application.Before closing the browser, let’s take a moment and look at thebrowser developer tools. In Chrome I’ll press F12.The exact tools you see here depend on the browser you are using.I’m using Chrome. Most modern browsers provide a console tab as partof the development tools. This is always the first place to look ifthe page does not appear as expected or doesn’t appear at all.Errors, warnings, and other information is displayed here.Use the elements tab or DOM explorer to view the HTML displayed in the page.This is a depiction of the DOM or document object model.The document object model is a document model loaded into the browserand represents our HTML as a node tree where each node is a part ofour HTML. Notice these scripts listed here.These aren’t in our source index.html file.We’ll talk about these bundles, what they are and how they got herein the Building, Testing, and Deploying with the CLI module later inthis course. Here is our selector tag.Open the selector tag and we see the HTML that we defined in ourcomponent’s template. This view is a great way to see the HTML forthe rendered page. There is also a debugger option available here onthe sources tab to view and debug our code.Since the Angular CLI uses Webpack, our TypeScript files are listedunder the Webpack node here. And because the Angular CLI servefeature generates the map file, we can debug our TypeScript directly.We can set a break point, refresh the browser, and it hits that break point.We can step through and check the value of any of our properties.Click here to resume. Use these debugging features any time you need them.Now let’s finish up this module with some checklists we can use as webuild our own components.
Checklists and Summary
Templates, Interpolation, and Directives
To build the user interface for our application in Angular we createa template with HTML. To really power up that user interface, we needAngular’s data binding and directives.Welcome back to Angular: in these next two modules we create theuser interface using templates, directives, and data binding.Web applications are all about the user interface and Angular makes iteasier to build rich and powerful user interfaces.Angular gives us data binding so we can easily display information andrespond to user actions. With Angular directives we add logic to ourHTML such as if statements and for loops and with Angular components,we build nested user interface fragments such as an image rotator orrating stars. We’ve seen that an Angular component is a view definedwith a template, its associated code defined with a class,and additional information defined with metadata and set using acomponent decorator. In these next two modules we’ll focus ontechniques for building the template.In this module we evaluate the different ways we can build a templatefor our component and demonstrate how to create a linked template forour view. Then we’ll build a component associated with that templateand use it as a directive. We’ll detail how to set up data bindingusing interpolation and display the value of our component classproperties in the view. We need some basic logic in the template sowe’ll leverage Angular’s built-in directives.In the next module we’ll look at additional data binding techniques.Looking at our application architecture we currently have theindex.html file and our root app component in place.So we have a working sample application, but it doesn’t look like much.What we really want is a list of products.In this module we’ll begin work on the product list component todisplay that list of products. Let’s get started.
Building a Template
In the prior module we built an inline template for our app component.We used the template property to define the template directly in thecomponent’s metadata, but this is not the only way we can build atemplate for our components.We can use the template property and define an inline template using asimple quoted string with single or double quotes, or we can definean inline template with a multi-line string by enclosing the HTMLand ES 2015 back ticks. The back ticks allow composing a string overseveral lines, making the HTML more readable.We use this technique to build our template in the last module.There are some advantages to defining an inline template using one ofthese two techniques. The template is directly defined within thecomponent, keeping the view and the code for that view in one file.It is then easy to match up our data bindings with the classproperties, such as the page title in this example; however, there aredisadvantages as well. When defining the HTML in a string,most development tools don’t provide IntelliSense, automaticformatting, and syntax checking. Especially as we define more HTMLin the template these issues become challenges.In many cases the better option is to define a linked template withthe HTML in its own file. We can use the template URL property in thecomponent metadata to define the URL of our HTML file.Let’s use this technique and build a linked template for our productlist view. Here is our ultimate goal for the product list view.The view has a nice heading. A filter by box at the top allows theuser to enter a string. The user-entered string is displayed here andthe list of products is filtered to only those with a product namecontaining that string. The products are listed in a neat table witha nicely formatted header. The show image button shows an image foreach product. The product name is a link that displays the productdetail view, which we’ll build later in this course.To make this page look nice with very little effort, we use theTwitter Bootstrap styling framework.You don’t need to have experience with this framework and if you’reusing the starter files, you don’t even have to install it.I’ve already included what we need, but if you want to find out moreabout the Twitter Bootstrap styling framework, check out this link.Now let’s jump into a demo and start building the template for ourproduct list view. When we last saw our sample application we hadcompleted the app component. Now we want to add an external templatefor the product list component. By convention, each feature of theapplication has its own folder under the app folder.So let’s add a new folder here and name it products.In that folder we’ll create the template for our product list component.By convention, the name of the template is the same name as thecomponent with an HTML extension.We’ll call our product list component product-list.component.html.Let’s widen that up a little bit.Now we are ready to create the HTML for our template.Let’s start with the heading. We’re using Twitter Bootstrap styleclasses here to display the content in a panel and display the headingas the panel heading. In the heading we display product list.If you don’t want to type in all of this code, you can copy it fromthe APM final folder provided in my GitHub repository as detailed inthe first things first module earlier in this course.Next is the filter by. We define an input box for entry of the filterstring and we add text that displays the user entered filter.We again use Twitter Bootstrap style classes to lay out the input boxand text into rows. Now let’s build the table.We’ll use Twitter Bootstrap’s table style classes.We have a table header. The first column header is a button to showthe product image and here is the table body.Hmmm. We definitely don’t want to hard code in the products here solet’s leave the table body empty for now.So we have the start of a template defined for our component.Now what? If you said we need to build the component, you are exactly right.
Building the Component
Remember the steps for building a component that we covered in thelast module? We define a class, we add a component decorator todefine the metadata and specify the template, and we import what we need.The only thing that’s really different from the component we createdin the last module is the template property.Here are using templateUrl to define the location of our linkedtemplate instead of defining an HTML string.Notice the syntax of the path here.If we follow the convention of defining the template HTML file in thissame folder as the associated component we can use a relative path byspecifying ./. Let’s jump right back to the demo and give this a try.We are back with the sample application exactly where we left it andwe are ready to build a new component.We start by creating a new file in the products folder.We’ll name it using the component naming convention, .componentbecause it is an Angular component and .ts for the extension.Then we create the class, export class ProductListComponent.We’re exporting this class so it is available to other parts of the application.Next we decorate the class with the component decorator.It is the component decorator that makes this class a component and weknow what that underline means. We need the import statement.Let’s pass an object into the component decorator with the appropriate properties.For the selector we’ll set pm.products.We’ll use the same prefix as in the app component to distinguish theselector as part of the product management application.Then we define the template URL. Here we provide the path to ourHTML file. Since we defined the HTML file in this same folder as thecomponent, we can use the ./ relative path syntax here.So now we have our template defining our view, our class which definesour associated code, and the component decorator that defines the metadata.Our component is complete and we’re ready to use it, but how?
Using a Component as a Directive
Here is our newly created product list component and here is the appcomponent we created earlier. Note that I’ve excluded some of thecode here on this slide such as the import statements and classdetails for a better fit. We’ll see the complete code when we getback to the demo. When a component has a selector defined, as we havehere, we can use the component as a directive.This means that we can insert this component’s template into any othercomponent’s template by using the selector as an HTML tag, like this.The product-list.components template is then inserted into thislocation in the app.components template.So this is the first step when using a component as a directive.Use the name defined in this selector as an HTML tag in anothercomponent’s template. When this template is displayed, Angular looksfor a component that has a selector with this name.We could have hundreds of components in our application.How does our application know where to look for this selector?The application looks to the Angular module that owns this componentdefined all of the directives that are visible to this component.Every Angular application must have at least one Angular module,the root application module commonly called AppModule.Currently our AppModule declares our root application component,AppComponent. A component must belong to one and only one Angular module.Because the AppModule declares the AppComponent, the AppComponentbelongs to the AppModule. The AppModule Bootstraps the applicationwith this component so it is the first component that is loaded forour application. Our AppModule also imports the system BrowserModuleto pull in the features it needs to run this application in a browser.So this is what our AppModule currently looks like.An Angular module defines the boundary or context within which thecomponent resolves its directives and dependencies.So when a component contains a directive, Angular looks to thecomponent’s module to determine which directives are visible to that component.What does that mean for us? Well, for Angular to find the pm productsdirective used in the AppComponent, the product list component mustalso be declared in this Angular module.This is the second step when using a component as a directive.We need to ensure that the directive is visible to any component thatuses it. There are two ways to expose a directive in an Angular module.We can declare the component in the Angular module as we show here,or if the component is already declared in another Angular module,we can import that module similar to how we import BrowserModule here.Now let’s jump back to the demo and give this a try.We are back in our sample app. We defined a selector for our productlist component here so we can use it as a directive in any other component.Let’s use it in the AppComponent.Open the AppComponent file. So instead of displaying my firstcomponent, we’ll display our new product list template here.Replace the div tags with pm-products.Are we ready to see our result in the browser?And our page does not display. Let’s use our F12 tools to see why.The key part of this error is that we have a template parse error.Pm-products is not a known element and with this error, Angular givesus a solution. If pm-products is an Angular component and in our caseit is, then verify that it is part of this module.Ah, yes! We didn’t do step 2 and declare it in our application’sAngular module. Let’s go back to the code.We’ll open the AppModule and add ProductListComponent to thedeclarations array. Well, we’re getting a squiggly line here.That means we have an error. Any guess as to what’s wrong?If you said we’re missing the import, you are correct.Everything we declare must be imported.With VS Code this is easy. Notice the light bulb icon on the left.It is indicating that it has a quick fix for this underlined issue.Click the light bulb and select the desired fix.In this case there is only one option and VS Code adds the appropriateimport line for us. Cool! There are some issue with the resultingimport statement. First, it uses double quotes.Since I’m standardizing on a single quote style throughout my classcode, I’ll change it to single quotes.Second, it does not take advantage of relative pathing.I’ll change it to ./. In future demos, I’ll continue to make thesechanges behind the scenes so you won’t have to watch me scroll up andfix them each time. Now that our syntax error is gone, let’s try it again.There’s our page! It’s not complete and it’s not interactive yet,but we have the basics in place.So we successfully used our product list component as a directive.We added the selector as the directive in the containing component’s template.We declared the component to the application’s Angular module and weadded the appropriate import statement.Now we are ready to power up our user interface with data binding andsome built-in Angular directives.
Binding with Interpolation
In Angular, binding coordinates coordination between the component’sclass and its template and often involves passing data.We can provide values from the class to the template for display andthe template raises events to pass user actions or user-entered valuesback to the class. The binding syntax is always defined in the template.Angular provides several types of binding and we’ll look at each of them.In this module we cover interpolation; the remaining data bindingtechniques are covered in the next module.The double curly braces that signify interpolation are readily recognizable.The page title in this example is bound to a property in thecomponent’s class. Interpolation is a one-way binding from the classproperty to the template so the value here shows up here.Interpolation supports much more than simple properties.We can perform operations such as concatenation or simple calculations.We can even call a class method such as getTitle shown here.We use interpolation to insert the interpolated strings into the textbetween HTML elements as shown here, or we can use interpolation withelement property assignments as in this example.Here we assign the innerText property of the h1 element to a bound value.Both of these examples display the same result.The syntax between the interpolation curly braces is called a template expression.Angular evaluates that expression using the component as the context.So Angular looks to the component to obtain property values or to call methods.Angular then converts the result of the template expression to astring and assigns that string to an element or directive property.So any time we want to display read-only data, we define a propertyfor that data in our class and use interpolation to display that datain the template and if we need to perform simple calculations or geta result from a method, we can do that with interpolation as well.Let’s give this a try. Looking at the product list template from oursample application, we hard-coded in the page title here in the heading.Binding the heading to a property in the class instead of hard-codingit in the HTML makes it easier to see and change when working on thecode and we could later retrieve this text from a file or database.Let’s start by adding a property in the class for the page title.We’ll open the component to the right and close down the explorer.Here in the class we specify the property name.We’ll call it pageTitle and because we are using TypeScript we definethe type for this property. Lastly, we assign a default value,Product List. With the page title property in place we can now bindto the page title property in the template.We replace the hard-coded product list here with interpolation andspecify the name of the property.Now when this template is displayed, Angular assigns the string valueof the page title property to the inner text property of this divelement and product list will be displayed.Let’s see the result in the browser.With our binding, the page title appears as before.So we can confirm that it works, I’ve rearranged the windows so thatwe can see both the code and the browser.Now let’s make a change to our page title here.And we immediately see it in the browser.So our interpolation works. So any time we want to display the valueof a component property, we simply use interpolation.Now we’re ready to add some logic to our template.
Adding Logic with Directives: ngIf
We can think of a directive as a custom HTML element or attribute weuse to power up and extend our HTML.We can build our own custom directives or use Angular’s built-in directives.Previously in this module we’ve seen how to build a component and useit as a custom directive. We use the pm-products directive to displayour product list template.In addition to building our own custom directives we can use Angular’sbuilt-in directives. The built-in Angular directives we’ll look atare structural directives. A structural directive modifies thestructure or layout of a view by adding, removing or manipulatingelements and their children. They help us to power up our HTML withif logic and for loops. Notice the asterisk in front of the directive name.That marks the directive as a structural directive.Let’s look at ngIf first.NgIf is a structural directive that removes or recreates a portion ofthe DOM tree based on an expression.If the expression assigned to the ngIf evaluates to a false value,the element and its children are removed from the DOM.If the expression evaluates to a true value, a copy of the element andits children are reinserted into the DOM.For example, say we only wanted to show the HTML table if there aresome products in a list of products.We use ngIf on the table element and set it to products andproducts.length. If the products variable has a value and theproducts list has length, the table appears in the DOM.If not, the table element and all of its children are removed fromthe DOM, but didn’t we just say that an Angular module defines theboundary or context within which the component resolves its directivesand dependencies? How will our application find this ngIf directive?Looking back at the illustration of our AppModule, we see that itimports BrowserModule. Luckily for us, BrowserModule exposes thengIf and ngFor directives. So any component declared by the AppModulecan use the ngIf or ngFor directives.With that settled, let’s try out the ngIf directive.We are back in the sample application, looking at theproduct-list.component and its template.We only want to display this table of products if there are someproducts to display. So the first thing we need is a property to holdthe list of products. Where do we define that products property?In the component’s class of course.We’ll add a products property here.Hmmm. But what is the type of this property?Well, we want an array of product instances, but we don’t currentlyhave anything that defines what a product is.We’ll have a better solution in a later module, but for now we’ll justdefine products as an array of any.In TypeScript we use any as the data type any time we don’t know ordon’t care what the specific data type is.We need to populate our array, but where do we get the data?In many cases we would communicate with a backend server to get this data.We’ll look at how to do that later in this course.For now we’ll just hard code in a set of products.If you are coding along, consider copying a few of the products fromthe products.json file provided with the starter files under the APIproducts folder. With the products property in place, we’re ready touse it in the HTML. We want to put it on the table element becausethat is the element we want to add or remove from the DOM.Type *ngIf= and then our expression in closed end quotes.We only want to show the table if there is a list of products and thatlist of products contains some elements.Let’s see what this looks like in the browser.We see the table header so we know our table is displayed.Let’s try this. Let’s comment out the product property assignment.Bring up the browser again and we see that the table disappeared.Now if we uncomment out our table and look again at the browser,our table reappears. With ngIf the associated element and itschildren are literally added or removed from the DOM.But notice that we still aren’t populating the table with our products.Let’s do that next.
Adding Logic with Directives: ngFor
Another structural directive is ngFor.NgFor repeats a portion of the DOM tree, once for each item in aniterable list. So we define a block of HTML that defines how we wantto display a single item and tell Angular to use that block fordisplaying each item in the list.For example, say we want to display each product in a row of a table.We define one table row and its child, table data elements.That table row element and its children are then repeated for eachproduct in the list of products.The let keyword here creates a template input variable called product.We can reference this variable anywhere on this element, on anysibling element, or on any child element and notice the of instead ofin here. We’ll talk more about that in a moment.For now, let’s jump back to our demo.We are once again looking at the product list component and its template.Here in the table body we want to repeat a table row for each productin the list of products. In the table body, we’ll add a tr elementfor the table row and in the tr element we’ll specify the ngFor.*ngFor= quote, let product of products, end quote.Next we’ll add the child elements.We’ll insert a td or a table data element for each property of theproduct that we want to display in the table.We’ll need to match them up with the table header elements.The first column displays the product image.Let’s skip the image for now. We’ll add that in the next module,but we’ll still add the td element as a placeholder.The next table header says product so in this column we want theproduct name. We’ll use interpolation to bind to the product’s nameby using the local variable product and a dot to drill down to theproduct properties. We want product name here.How did we know that property name?Looking here at the product list component we see the product propertynames here. So these are the names we use in the interpolationtemplate expressions. Next I’ll add td elements for some of the otherproduct properties. So for each product in our list of products,we will get a tr element for a table row and td elements for table data.Want to see how this looks in the browser?Wow! We have our products. Doesn’t that look nice?Well, our price is not very well formatted and it doesn’t have acurrency symbol. We’ll fix that with pipes in the next module.Looking back at the component we defined an array for our list of products.In the template we laid out the HTML to display one product.The product is displayed in a table row with product properties in theappropriate columns. Using an ngFor structural directive, we repeatthis table row and its columns for each product in the list of products.So why is this ngFor syntax product of products and not product in products?The reasoning for this has to do with ES 2015 for loops.ES 2015 has both a for of loop and a for in loop.The for of loop is similar to a foreach style loop.It iterates over an iterable object such as an array.For example, say we have an array of persons’ nicknames.If we use for of to iterate over this list, we’ll see each nicknamelogged to the console. The for in loop iterates over the propertiesof an object. When working with an array such as this example,the array indexes our innumerable properties with integer names andare otherwise identical to general object properties.So we see each array index logged to the console.To help remember the difference, think of in as iterating the index.Since the ngFor directive iterates iterable objects, not theirproperties, Angular selected to use the of keyword in the ngFor expression.Now let’s finish up this module with some checklists we can use as wework with templates, interpolation, and directives.
Checklists and Summary
Checklists are a great way to recheck our understanding and our work.Let’s start with a template. Use an inline template when buildingshorter templates, then specify the template property in the component decorator.Use double or single quotes to define the template string, or use theES 2015 back ticks to lay out the HTML on multiple lines.When using inline templates there is often no design time syntaxchecking so pay close attention to the syntax.Use linked templates for longer templates, specify the templateUrlproperty in the component decorator and define the path to theexternal template file.This one is a more visual checklist.After building the template, we build its component and learn how touse that component as a directive.Remember our steps? First we use the directive as an element in thetemplate for any other component.We use the directive component selector as the directive name.We then declare the component so it is available to any templateassociated with this Angular module.We add the component to the declarations array passed into the@NgModule decorator of the Angular module.Angular’s data binding was introduced in this module with a look at interpolation.Interpolation is one-way binding from a component class property to anelement property. Interpolation is defined with curly braces and atemplate expression. That expression can be a simple property,a concatenation, a calculation, or a method call.Note that no quotes are needed when using interpolation.And we saw how to use two of Angular’s structural directives,ngIf and ngFor. When using these structural directives, be sure toprefix them with an asterisk and assign them to a quoted string expression.Use ngIf to add or remove an element an its children from the DOMbased on an expression. If the assigned expression is evaluated to bea true value, the element is added to the DOM.If false, the element is removed from the DOM.Use ngFor to repeat an element and its children in the DOM for eachelement in an iterable list.Define the local variable with let and use of, not in, when definingthe ngFor expression.In this module we evaluated the differences between an inline templateand a linked template and we created a linked template.We then built a component for that template and learned how to usethat component as a directive.We took a first look at Angular data binding through interpolation andpowered up our template by using built-in Angular directives.Here once again is our application architecture.In this module we started the product list component.Next up, let’s discover more of Angular’s data binding features andadd interactivity to the product list template.
Data Binding & Pipes
There is more to data binding than just displaying component properties.Welcome back to Angular: in this module we explore more databinding features and transform bound data with pipes.To provide a great interactive user experience we want to bind downelements to component properties so the component can change the lookand feel as needed. We can use bindings to change element colors orstyles based on data values, update font size based on userpreferences, or set an image source from a database field.And we want notification of user actions and other events from the DOMso the component can respond accordingly.For example, we respond to a click on a button to hide or show imagesand sometimes we want the best of both worlds using two-way binding toset an element property and receive event notifications of userchanges to that property.In this module we’ll use Angular’s property binding to set HTMLelement properties in the DOM.We walk through how to handle user events such as a button click withevent binding, and how to handle user input with two-way binding.Lastly, we’ll discover how to transform bound data with pipes.And here once again is our application architecture.We have the first cut of our product list component, but it doesn’thave any interactivity. In this module we’ll use data bindingfeatures to add interactivity to the product list component.Let’s get started.
Property binding allows us to set a property of an element to thevalue of a template expression.Here we bind the source property of the image element, to the imageURL property of the product, effectively defining the source of theimage from information in our component class.Our binding target is always enclosed in square brackets to the leftof the equals and identifies a property of the element.The binding source is always enclosed in quotes to the right of theequals and specifies the template expression.For comparison, here is a similar binding using interpolation.Note that in this case the element property is not enclosed in squarebrackets and the template expression is enclosed in curly braces withno quotes. Like interpolation, property binding is one way from thesource class property to the target element property.It effectively allows us to control our template’s DOM from ourcomponent class. When we can use property binding or interpolationto achieve the same result, which one is better?The general guideline is to prefer property binding overinterpolation; however, if you need to include the template expressionas part of a larger expression such as this example, you may need touse interpolation. Now let’s add some property binding to our sample application.Here we are back in the editor, looking at the product list componentand its associated template. Let’s use property binding to bind thesource of our product image. We’ll use an image element to displayour product image and we’ll use property binding to bind the image’ssource or src property so we enclose the src in square brackets.On the right side of the equals we define the template expression in quotes.We want to bind to the product’s image URL property from the productlist component class. Let’s also use property binding to bind thetitle property of the image to the product’s name.Let’s check out the result in the browser.Whoa! They’re big! But we do see images.If we hover over an image we see the image title, but this image israther large for display in our table.Let’s use property binding to set some style properties.Let’s add properties for the image width and image margin to ourcomponent class. The image width is a number so we specify its typewith a colon and then number. Let’s set it to 50.The image margin is also a number and we’ll set it to 2.Back in the template we use property binding to bind the image styles.We want to bind the style property width in pixels.We’ll bind that to the image width property from the component class.Notice that we don’t prefix this property with product because imagewidth is a property of the component class, not the product object.And we do the same with the style margin in pixels and set that to theimage margin class property.So now we’ve seen how to use property binding to bind severalproperties of the image element to properties of the component’s class.Looking again at the browser, that looks much better, but our imagesare always displayed. The Show Image button doesn’t work yet.To hook up the button we need to respond to user events.Let’s do that next.
Handling Events with Event Binding
Handling Input with Two-way Binding
When working with user entry HTML elements such as an input element,we often want to display a component class property in the templateand update that property when the user makes a change.This process requires two-way binding.To specify two-way binding in Angular we use the ngModel directive.We enclose ngModel in square brackets to indicate property bindingfrom the class property to the input element and parentheses toindicate event binding, to send a notification of the user-entereddata back to the class property.We assign this directive to a template expression.To help us remember which order to put the two sets of brackets,visualize a banana in a box. Square brackets for the box the outsideand parentheses for the banana on the inside.So now we have another Angular directive that we can use.Every time we want to use an Angular directive in a template, we needto consider how to make that directive visible to the componentassociated with that template.Recall that an Angular module defines the boundary or context withinwhich the component resolves its directives and dependencies.The illustration of our AppModule currently looks like this.We want to use the ngModel directive in our product list component,which is owned by AppModule. So in the AppModule we need to importthe appropriate system module that exposes the ngModel directive.Since the ngModel directive is most often used when building dataentry forms, ngModel is part of FormsModule so we import that here.Now the ngModel directive and any of the other Angular formsdirectives are visible to any component declared by AppModule,including our product list component. Now let’s give this a try.We are back in the editor and looking at the product component andits associated template. Recall that we defined a Filter By input boxhere and display the enter filter here.We’ll later use the filter to filter our list of products.Let’s start by adding a component class property for the list filter.This property is a string and we’ll set a default initial value forfiltering the list of products.We hard code the filter string here, but you can imagine that we storethe user’s last entered filter and use that as the default instead.With that we can set up the two-way binding.On the input element, we draw a banana in a box, then specify thengModel directive. We bind to the component class list filter property.We want to display the list filter here so we use interpolation.Recall that interpolation has no quotes.Are we done? Not quite. Let’s see what happens if we try to run.The page doesn’t appear. If we press F12 we see the error is,can’t bind to ngModel since it isn’t a known property of input.This is telling us that Angular can’t find the ngModel directive.Recall from the slides that the ngModel directive is part of theAngular module for forms called FormsModule.To expose this directive to our product list component we need toimport the forms module in the module that owns the product listcomponent, which is our AppModule.We start by importing FormsModule from Angular Forms.We then add FormsModule to the imports array for the ngModel decorator.Why the imports array and not the declarations?Our directives, components, and pipes are declared here in thedeclarations array. Directives, components, and pipes we use fromother sources such as Angular itself or third parties are defined inexternal Angular module we add to the imports array here.Now that we’ve told Angular where to find the ngModel, let’s see the result.When the page displays we see cart as the default value.It is displayed here and here. If we modify the entry, notice thatthe displayed filter text is also updated.That’s because we are using two-way binding.Notice that the list of products is not yet filtered.We’ll do that in the next module.There is one more thing we do want to address now and that is the data formatting.That price should really look like a price and show the appropriatecurrency symbol.
Transforming Data with Pipes
With Angular’s data binding, displaying data is easy; just bind anelement property to a class property and we’re done.Well, not always. Sometimes that data is not in a format appropriatefor display. That’s where pipes come in handy.Pipes transform bound properties before they are displayed so we canalter the property values to make them more user friendly or morelocale appropriate. Angular provides some built-in pipes forformatting values such as date, number, decimal, percent, currency,uppercase, lowercase and so on.Angular also provides a few pipes for working with objects such asthe JSON pipe to display the content of an object as a JSON string,which is helpful when debugging and a sliced pipes, which selects aspecific subset of elements from a list.We can also build our own custom pipes as we’ll see in the next module.Let’s start with a simple example.Say we want to display the product code in lowercase.We can add the pipe character after the property in the templateexpression and then specify the lowercase pipe.The product code is then transformed into lowercase before it is displayed.We can also use pipes and property bindings.Add the pipe after the property in the template expression and specifythe desired pipe. In this example we specified the uppercase pipe sothe image title will appear in all caps.If needed, we can chain pipes. In this example the price istransformed into a currency. By default the currency pipe adds theall caps three-letter abbreviation of the local currency to the amount.If we want to display that abbreviation in lowercase, we can transformit again by simply adding another pipe.Some pipes support parameters. Parameters are defined by specifying acolon and the parameter value. For example, the currency pipe hasthree parameters. The desired currency code, a Boolean valueindicating whether to display the currency symbol, and digit info.The digit info consists of the minimum number of integer digits,the minimum number of fractional digits, and the maximum number offractional digits. The value here of 1.2-2 means at least one digitto the left of the decimal and at least two digits to the right of thedecimal and no more than two digits to the right of the decimal,effectively defining two decimal places.With that, let’s jump back to the demo.We specify the pipes in the template so we are looking at the productlist component template. Let’s add a lowercase pipe for the productcode and a currency pipe for the price.For the product code we simply insert the pipe character after theproperty in the template expression and type lowercase; that’s it.For the price we insert a pipe character and currency.That’s all that is required, but let’s try out a few of the parameters.We’ll specify USD true to display the dollar sign instead of thecurrency abbreviation and 1.2-2 to specify that we want at least onenumber to the left of the decimal place and two and only two numbersto the right of the decimal place. Let’s see how we did.Ah! Looking at the result, we now see the product code in lowercaseand the price displayed nicely as a currency.So we can easily perform simple data transformations using thebuilt-in pipes in the template expressions for our bindings.Feel free to try out some of the other pipes from the slides.Let’s finish up this module with some diagrams and a checklist we canuse as we work with bindings and pipes.
Checklists and Summary
Data binding makes it easy to display class properties from ourcomponent and set DOM element properties to our class property valuesto better control the view, and the component can listen for eventsfrom the DOM to respond as needed for an interactive user experience.There are four basic types of binding of Angular.Here is a diagram as a memory aide.Interpolation inserts interpolated strings into the text between HTMLelements or assigns element properties.Be sure to wrap the template expression in curly braces and no quotes.Property binding sets an element’s property to the value of a template expression.The binding target specifies a property of the element and must beenclosed in square brackets. The binding source specifies thetemplate expression and must be enclosed in quotes.Event binding listens for events and executes a template statementwhen the event occurs. The target event specifies an event name andmust be enclosed in parentheses. The template statement often definesthe name of the method to call when the event occurs and must beenclosed in quotes. Two-way binding displays a component classproperty and updates the property when the user makes a change.Use the banana in a box syntax with the ngModel directive.The binding source specifies the template expression and must beenclosed in quotes. Here are some things to remember when using ngModel.Define ngModel within the banana in a box for two-way binding.Be sure to add FormsModule from the Angular Forms package to theimports array of an appropriate Angular module, in this case, AppModule.This ensures that the ngModel directive is available to any templatedefined in a component associated with that module.We’ll talk more about Angular modules later in this course.The data we have in our component may not be in the format we want for display.We can use a pipe in a template to transform that data to a more userfriendly format. To use a pipe, specify the pipe character, the nameof the pipe, and any pipe parameters separated with colons.Here is an example of the currency pipe with three parameters.This module covered data binding and pipes.We looked at property binding, event binding, and two-way binding.Lastly we discovered how to transform bound data to a more userfriendly format using built-in pipes.And here once again is our application architecture.In this module we finished more of the product list component, but itcould be better. Next up we’ll see several techniques for improving our component.
More on Components
When building clean components we want to ensure everything isstrongly typed, our styles are encapsulated, we respond to appropriatelifecycle events, and we transform data to user friendly values as needed.Welcome back to Angular: in this module we learned several waysto approve upon our components.Components are one of the key building blocks of our application.The cleaner, stronger, and more durable we make these blocks,the better our application. So how we can make our components better?Strong typing helps minimize errors through better syntax checking andimproved tooling, but what if there is no predefined type for a property?To strongly type a property that has no predefined type we define thetype ourselves using an interface.If a component needs special styles we can encapsulate those styleswithin the component to ensure they don’t leak out to any othercomponent in the application. A component has a lifecycle managed by Angular.Angular provides a set of lifecycle hooks we can use to tap into keypoints in that lifecycle, adding flexibility and responsiveness to our application.As we saw in the last module, pipes provide a convenient way totransform bound data before displaying it in the view.We may have other application unique data transformation requirements.Luckily, we can build our own custom pipes.Any time we build and test a component once and nest it in severalplaces in the application we have minimized development time andimproved the overall quality of the application.In this module we explain interfaces and demonstrate how to use themto strongly type our objects. We look at how to encapsulate componentstyles, we introduce the component lifecycle and how to hook into itsevents, and we detail how to build a custom pipe.We cover building nested components in the next module.Looking at our application architecture, in this module we’ll addfeatures to improve the product list component.Let’s get started.
Encapsulating Component Styles
When we build the template for our component we sometimes need stylesunique to that template. For example, if we build a sidebarnavigation component we may want special LI or div element styles.When we nest a component that requires special styles within acontainer component we need a way to bring in those unique styles.One option is to define those styles directly in the templates HTML,but that makes it harder to see, reuse, and maintain those styles.Another option is to define the styles in an external style sheet.That makes them easier to maintain, but that puts the burden on thecontainer component to ensure the external style sheet is linked inthe index.html. That makes our nested component somewhat moredifficult to reuse, but there is a better way.To help us out with this issue, the component decorator has propertiesto encapsulate styles as part of the component definition.These properties are styles and styleUrls.We add unique styles directly to the component using the styles property.This property is an array so we can add multiple styles separated by commas.A better solution is to create one or more external style sheets andidentify them with the styleUrls property.This property is an array so we can add multiple style sheetsseparated by commas. By encapsulating the styles within thecomponent, any defined selectors or style classes are only applicableto the component’s template and won’t leak out into any other part ofthe application. Let’s try this out.Before we change any code, let’s look again at our product list viewin the browser. Notice the table headers; they could use a little color.So let’s build an external style sheet for our product list component.We’ll add a new file in the products folder and since this file onlycontains the styles for our product list component, we’ll call itproduct-list.component.css.In this style sheet we add a table header style.We can modify the thead element styles directly because this stylesheet is in encapsulated in this component and the styles defined herewon’t affect any other component in the application.We could add any other styles as needed to jazz up our product list component.To use this new style sheet we modify the product list component.In the component decorator we specify our unique style sheet.We add the styleUrls property and pass it an array.In the first element to the array we specify the path to our style sheet.Since we defined the css file in the same folder as the component,we can use the ./ relative path syntax.We could add more style sheets here separated with commas.Let’s review the result in the browser and we see that the tableheader is now a nice blue color. We can use the styles or styleUrlsproperty of the component decorator any time we want to encapsulateunique styles for our component.Next up, let’s dive into lifecycle hooks.
Using Lifecycle Hooks
Building Custom Pipes
Filtering a List
Checklists and Summary
We’ve covered several discrete topics in this module so we have achecklist for each one. First, interfaces.We use interfaces to specify custom types such as product in oursample application. Interfaces are a great way to promote strongtyping in our applications. When creating an interface, use theinterface keyword. In the body of the interface, define theappropriate properties and methods along with their types and don’tforget to export the interface so it can be used anywhere in our application.We implement an interface including built-in Angular interfaces toensure that our class defines every property and method identified inthat interface. Add the implements keyword and the interface name tothe class signature. Then be sure to write code for every propertyand method in the interface. Otherwise TypeScript displays the syntax error.We can encapsulate the styles for our component in the component itself.That way the styles required for the component are associated with thecomponent alone and don’t leak into any other parts of the application.Use the styles property of the component decorator to specify thetemplate styles as an array of strings.Use the styleUrls property of the component decorator to identify anarray of external style sheet paths.The specified styles are then encapsulated in the component.Lifecycle hooks allow us to tap into a component’s lifecycle toperform operations. The steps for using a lifecycle hook are:Import the lifecycle hook interface, implement the lifecycle hookinterface in the component class.This step is not required, but highly recommended.Then write the code for the hook method defined in the lifecycle hook interface.To build a custom pipe, import pipe and PipeTransform.Create a class that implements the PipeTransform interface.This interface has one method, transform.Be sure to export the class so the pipe can be imported from other components.Write code in the transform method to perform the neededtransformation and decorate the class with the pipe decorator.We can use a custom pipe in any template anywhere we can specify a pipe.In an Angular module, import the pipe.In the metadata, declare the pipe in the declarations array.Then any template associated with a component declared in that Angularmodule can use that pipe. In a template, immediately after theproperty to transform, type a pipe character, specify the pipe name,and enter the pipe arguments if any, separated by colons.This module provided a set of techniques for improving our components.We walked through how to use an interface to strongly type our custom objects.We saw how to encapsulate styles within a component.We were introduced to the component lifecycle and how to tap into thatlifecycle with lifecycle hooks and we discovered how to build a custompipe that we can use in any component template.So in this module we’ve completed the product-list.component. Yay!Next up we’ll see how to build nested components and build this start component.
Building Nested Components
Our user interface design may include features that are complex enoughto be separate components or that are reusable across our views.Welcome back to Angular: in this module we see how to buildcomponents designed to be nested within other components and we’lldiscover how to establish communication between the nested componentand its container component.Just like nesting dolls, we can nest our components.We can nest a component within another component and nest thatcomponent within yet another component and so on.And because each component is fully encapsulated, we expose specificinputs and outputs for communication between a nested component andits container, allowing them to pass data back and forth.There are two ways to use a component and display the component’s template.We can use a component as a directive.We saw how to use a component as a directive when we displayed theAppComponent template in the index.html file.The pm-root directive is defined as the AppComponent selector.The template is then displayed within the directive tags.We use the same techniques with nested components.Alternatively we can use a component as a routing target so it appearsto the user that they’ve traveled to another view.The template is then displayed in a full page style view.We’ll use this technique later in this course to route to our productlist view. Our product list view is currently used as a directive,but that’s only because we have not yet covered routing.In this course module we’ll focus on building a nested component.So what makes a component nestable? Technically speaking, any of ourcomponents could be nested if they have a selector defined in thecomponent decorator, but does it really make sense to nest a largeview such as product list?For our purposes we’ll define a component as nestable if its templateonly manages a fragment of a larger view,if it has a selector so it can be used as a directive,and optionally if it communicates with its container.In this module we’ll build a nested component.Then we’ll review how to use that nested component as a directive in acontainer component. We’ll examine how to pass data to the nestedcomponent using a property with the input decorator.And how to pass data out of the nested component by raising an eventdefined with the output decorator.In our sample application, to improve the user experience we want toreplace the rating number displayed in the product list component with stars.In this module we’ll build this star component and nest it within theproduct list component. Let’s get started.
Building a Nested Component
Here is a visual representation of a component that is nestable.Here is another component. It wants to use the nestable component inits template. We then refer to the outer component as the containeror parent component and we refer to the inner component as the nestedor child component. When building an interactive application,the nested component often needs to communicate with its container.The nested component receives information from its container usinginput properties and the nested component outputs information back toits container by raising events.In our sample application we want to change the display of thefive-star rating from this to this.Displaying the rating number using a visual representation such asstars makes it quicker and easier for the user to interpret themeaning of the number. This is the nested component we’ll build inthis module. For the star component to display the correct number ofstars, the container must provide the rating number to our starcomponent as an input. And if the user clicks on the stars, we wantto raise an event to notify the container.Let’s jump right in and build our star component.When we last saw our sample application we had completed the productlist component. Now of course we want to change it.Instead of displaying a number for the rating here, we want to display stars.Instead of adding the code to the product list component to displaythe stars, we want to build it as a separate component.This keeps the template and logic for that feature encapsulated andmakes it reusable. So let’s begin by creating a star component.The star component can be used by any feature of the application so itreally doesn’t belong in our products folder.We’ll instead put it in a shared folder where we’ll put all our shared components.If you are using the starter files, I’ve already created this folderand included the template and style sheet for our component here.Now we are ready to build the star component.We begin by creating a new file. We’ll name it star.component.ts.We then create this component just like we’d create any othercomponent, starting with the class; export, class, star component.What’s next? Yes, we decorate the class with the component decorator.Recall that it is this component decorator that makes this class a component.As always, it shows us a syntax error here because we are missing,yes, our import. Time to set the component decorator properties.For the selector we’ll set pm-star.For the templateUrl we provide the path to the HTML file provided withthe starter files. We’ll add the styleUrls property and in the arraywe’ll set the first element to the path of the style sheet that wasalso provided. Since both files are in the same folder as thecomponent, we can use relative pathing.Now let’s take a peek at the star component template.Here it displays five stars. It then crops the stars based on adefined width. This technique can then display partial stars such asfour and a half of the five stars by setting the width such that onlyfour and a half of the stars appear.Recall what this syntax is called? This is property binding.We’re using it here to set the style width and here to bind the titleproperty to display the numeric rating value.For these bindings to work we need two properties in the components class.The rating and the star width. Let’s add these two properties.We want a rating property, which is a number and defines the rating value.Since we don’t yet have a way to get this value, let’s hard code it tofour for now so we’ll see some stars.And we need the star width. This value is calculated based on the rating.So where do we put that calculation?Well, we’d want the star width recalculated any time the containerchanged the rating number. So let’s tap into the OnChanges lifecyclehook as we discussed in the last module.We’ll implement the OnChanges interface and we’ll write code for thengOnChanges method identified in the OnChanges interface.In this method we’ll convert the rating number to a star width basedon the width of our stars. Our component is now complete and we’reready to nest it in another component. How do we do that?
Using a Nested Component
Now we are ready to nest our new component within another component.We do that by using our nested component as a directive and followingthe same steps we covered earlier in this course.Here is a shortened form of the code for a container component and itstemplate and here is the nested component we just created.Instead of displaying the star rating number, we want to display the stars.So the container component uses the nested component by specifying itsdirective here. This identifies where in the container to place thenested component’s template. As we’ve seen in prior demos, when weuse a component as a directive, we need to tell Angular how to findthat directive. We do that by declaring the nested component in anAngular module. How do we know which Angular module?Well, we still only have one Angular module, AppModule.In our example, the ProductList-Component’s template wants to use thestar component so we add the declaration to the same Angular modulethat declares the product list component.We define the nested component in the declarations array of thengModule decorator and as always, define what we need by adding animport statement. Let’s jump right back to our demo.Our star component is now shown here on the right.We want to use our star component in the product list template thatis here on the left. In the table data element we want to replacethe display of the star rating number with our star component.To do that we simply replace the binding with our directive.Now our product list template will display our stars here.Next we need to tell Angular where to find this directive.Since we only have one Angular module we’ll add the declaration forthe nested component there. Add the star component to thedeclarations array passed into the ngModule decorator.These are the same steps we followed earlier in this course to use acomponent as a directive. Nothing new here so far.Let’s see what we did. We have stars! Yes!Hmmm, but we see five of them. Let’s clear out the filter.Yes, we see five every time. Hover over the stars and we see ourhard-coded star rating is 4. It seems that our star width is notbeing set. Let’s look at the code again.We set the star width property in the ngOnChanges method when theonChanges lifecycle event occurs, but the onChanges lifecycle eventnever occurs because onChanges only watches for changes to input properties.We don’t have any input properties so we have two problems here.Our onChanges event does not fire and we don’t currently have a wayto get the correct rating number from the container.Let’s see how input properties can solve both of these issues.
Passing Data to a Nested Component Using @Input
If a nested component wants to receive input from its container,it must expose a property to that container.The nested component exposes a property it can use to receive inputfrom its container using the aptly named input decorator.We use the input decorator to decorate any property in the nestedcomponent’s class. This works with any property type including an object.In this example we want the rating number passed into the nested component.So we mark that property with the input decorator.The container component then passes data to the nested component bysetting this property with property binding.When using property binding, we enclose the binding target in square brackets.We set the binding source to the data that the container wants to passto the nested component. In this example, the product list templatepasses the product’s star rating number.The only time we can specify a nested component’s property as aproperty binding target on the left side of an equals is when thatproperty is decorated with the input decorator.So in this example, the product list template can bind to the rating,but not the star width. Let’s give this a try.The star component wants to expose the rating property to itscontainer so the container can provide the rating number.We’ll add the input decorator then to the rating property.The input decorator is a function so we add parentheses.We don’t need to pass anything to this function so that’s it,and let’s remove this default value.Now that we can get the value from the container, we don’t need that here.In our example, we decorate only one property of the nested componentwith the input decorator, but we are not limited to one.We can expose multiple input properties as needed.In the container’s template we use property binding and define thenested component’s input property as the target of the binding.Then we set the binding source to the value we want to pass into thenested component. In this example, we pass the product’s star rating.That’s it! The product star rating property is now bound to therating input property of the nested component.Any time the container data changes, the onChanges lifecycle eventis generated and the star width is recalculated.The appropriate number of stars are then displayed.Let’s check it out in the browser. Well, that looks better.Well, we’re not really displaying the 0.2 stars here.Our algorithm could use some improvement, but you get the idea.But what if we want to send data back from our nested component to our container?Let’s look at that next.
Passing Data from a Component Using @Output
We just saw how the container passes data to the nested component bybinding to a nested component property that is decorated with theinput decorator. If the nested component wants to send informationback to its container, it can raise an event.The nested component exposes an event it can use to pass output to itscontainer using the aptly named output decorator.We can use the output decorator to decorate any property of the nestedcomponent’s class; however, the property type must be an event.The only way a nested component can pass data back its container iswith an event. The data to pass becomes the event payload.In Angular an event is defined with an event emitter object.So here we create a new instance of an event emitter.Notice the syntax here. TypeScript supports generics.If you are not familiar with generics, this syntax allows us toidentify a specific type that the object instance will work with.When creating an event emitter, the generic argument identifies thetype of the event payload. If we want to pass a string value to thecontainer in the event payload, we define string here.If we want to pass an integer, we define number here.If want to pass multiple values, we can specify an object here.In this example, we define a notify event with a string payload.When the user clicks on the stars, the star component receives thatclick event. We use event binding in the star component template tocall the star component’s onClick method.In the onClick method we use the notify event property and call itsemit method to raise the notify event to the container.If we want to pass data in the event payload, we pass that data intothe emit method. In this example, the onClick method raises thenotify event and sets the event payload to a string message.The container component receives that event with the specified payload.In the container component’s template we use event binding to bind tothis notify event and call a method.We access the event payload using \(event.The only time we can specify a nested component’s property as an eventbinding target on the left side of an equals is when that property isdecorated with the output decorator.Lastly, the container component provides the method to execute whenthe notify event occurs. Since the event payload is a string, thisfunction takes in a string. Here we can perform any desired action.Hmmm. Lots of moving parts here. Let’s jump into the code and try it out.We are back in the sample application looking at the star component.What is our goal? When the user clicks on one of the rating stars,we want to display that rating in the header.This feature may not be incredibly useful, but it will demonstrate howto pass events from our nested child component to the parent container component.So our first task is to respond to the user’s click event on the star rating.We do that using event binding in the star component’s template.We’ll bind the div elements click event to an onClick method in thestar component class. Next, let’s implement this onClick method inthe component. Hmmm. Somehow in this method we need to send out anotification of this click to the container.For now let’s just log out that the rating was clicked.In this example we use the ES 2015 back ticks to define a template string.This allows us to embed the rating directly into the string.Let’s try it out in the browser.Open the developer tools and click on the rating stars.We see it logged to the console here.Going back to the code, we need to send out a notification to thecontainer when the user clicks on the star rating of the nested component.Recall from the slides how the nested component communicates with its container?It uses an event with the output decorator.Let’s define an event property in the nested component.We’ll call it ratingClicked. Since this must be an event, we definethe type of this property to be EventEmitter.We’ll use the provided quick fix to add EventEmitter to the import statement.We want to pass a string to the container as part of this event so wespecify string as the generic argument.We then set the rating clicked property to a new instance of event emitter.This sets up our event. Next we decorate our event property with theoutput decorator so that the container can respond to this event.The output decorator is a function so we add parentheses.We again use the quick fix to add output to the import statement.In this example we are decorating only one property of the nestedcomponent with the output decorator, but we are not limited to one.We can expose multiple output properties as needed, as long as they’re events.Here in our onClick method we want to raise this event to thecontainer and pass along our message.We use the event property and call its emit method, passing in thedesired string. The emit method raises the event.Now that we are raising this ratingClicked event to our container,how does the container listen for and respond to this event?It uses event binding. In this example, our container is the productlist component. In the product list component template we bind to theevent raised from the star component using event binding.For event binding we use parentheses and specify the name of the eventto listen for. We want to listen for the ratingClicked event raisedby the star component. Now what do we want to do when the event is raised?We’ll need to define a method in the product list component class toprocess the event. Let’s call that method onRaitingClicked.Recall that we are passing a string when raising this event so let’spass that string into our onRatingClicked method.We do that using \)event. $event passes along any informationassociated with a generated event.Next we need to write the code for this method in the product listcomponent class. Our template is expecting that we have a methodcalled onRatingClicked and is passing a string message with the event.Our method returns no value so we define the return type as void.Now that we have the message from the event, what do we want to dowith it? Our goal was to display it on the page title so we’ll modifythe page title to display product list and the message from the nestedstar component. Okay, yes. That is not a very real-world example,but I wanted to keep this as straightforward as possible.We’d have a better example if the nested component contained an inputbox and we could pass the user’s input in the event payload, but youget the general idea here. Let’s see how this works in the browser.Click on the star rating and we see the page title changed to displaythe message received from the nested component. Success!We just saw how the container passes data to the nested component bybinding to a nested component property that is decorated with theinput decorator and how the nested component uses an event propertydecorated with the output decorator to raise events.We can think of the properties decorated with the input or outputdecorators as the public API of the nestable component.Everything else in the component is encapsulated and only accessibleto the component’s template and class.Let’s finish up this module with some checklists we can use as webuild nestable components.
Checklists and Summary
We build a nested component using the same techniques we use to buildany other Angular component. We won’t review that again here.Let’s instead lay out a checklist for inputs and outputs.Decorate a nested component property with the input decorator any timeit needs input data from its container.Any type of component property can be decorated with the input decorator.Don’t forget the @ prefix and since the input decorator is a function,follow it with open and closing parentheses.Decorate a nested component property with the output decorator anytime it needs to raise events and optionally pass information back toits container. Only properties of type EventEmitter should be markedwith the output decorator. Use the EventEmitter’s generic argument tospecify the type of the event payload and use the new keyword tocreate an instance of the EventEmitter.Don’t forget the @ prefix and since the output decorator is afunction, suffix it with open and closing parentheses.In a container component’s template, use the nested component as a directive.For the name of the directive, see the nested component’s selector property.Use property binding to pass data to the nested component.Any property of the nested component that is decorated with the inputdecorator can be used as a binding target.Use event binding to respond to events from the nested component.Any event that is decorated with the output decorator can be used asthe binding target. And use $event to access the event payload passedfrom the nested component.This module was all about nested components.We began by building a component that could be nested within other components.We then walked through how to use the nested component within a container.We saw how to pass data into the nested component by binding to aproperty marked with the input decorator, and we discovered how topass data out of the nested component by raising an event marked withthe output decorator.In this module we built the star component and nested it within theproduct list component. We can reuse this component in any othercomponent of the application such as the product detail component.Next up, let’s check out how to build an Angular service so we won’tneed hard-coded product data in our component.
Services and Dependency Injection
Components are great and all, but what do we do with data or logicthat is not associated with a specific view or that we want to shareacross components? We build services.Welcome back to Angular: Deborah Kurata here, at your service and in this module we create aservice and use dependency injection to inject that service into anycomponent that needs it.Applications often require services such as a product data service ora logging service. Our components depend on these services to do theheavy lifting. Wouldn’t it be nice if Angular could service up thoseservices on a platter? Well, yes it can, but what are services exactly?A service is a class with a focused purpose.We often create a service to implement functionality that isindependent from any particular component, to share data or logicacross components, or encapsulate external interactions such as data access.By shifting these responsibilities from the component to a service,the code is easier to test, debug, and reuse.In this module we start with an overview of how services anddependency injection work in Angular.Then we’ll build a service, we’ll register that service, and we’llexamine how to use the service in a component.We currently have several pieces of our application in place, but wehard-coded our data directly in the product list component.In this module we’ll shift the responsibility for providing theproduct data to a product data service. Let’s get started.
How Does It Work?
Before we jump into building a service, let’s take a look at howservices and dependency injection work in Angular.In this diagram our service is here and our component that needs theservice is here. There are two ways our component can work with this service.The component can create an instance of the service class and use it.That simple and it works, but the instance is local to the componentso we can’t share data or other resources and it will be moredifficult to mock the service for testing.Alternatively we can register the service with Angular.Angular then creates a single instance of the service class called asingleton and holds onto it. Specifically, Angular provides abuilt-in injector. We register our services with the Angular injectorwhich maintains a container of created service instances.The injector creates and manages the single instance or singletonof each registered service as required.In this example, the Angular injector is managing instances of threedifferent services: log, math, and my service, which is abbreviated svc.If our component needs a service, the component class defines theservice as a dependency. The Angular injector then provides orinjects the service class instance when the component class is instantiated.This process is called dependency injection.Since Angular manages the single instance, any data or logic in thatinstance is shared by all of the classes that use it.This technique is the recommended way to use services because itprovides better management of service instances, it allows sharing ofdata in other resources, and it’s easier to mock the services fortesting purposes. Now let’s look at a more formal definition ofdependency injection.Dependency injection is a coding pattern in which a class receives theinstances of objects it needs called its dependencies from an externalsource rather than creating them itself.In Angular this external source is the Angular injector.Now that we’ve got a general idea of how services and dependencyinjection work in Angular, let’s build a service.
Building a Service
Are we ready to build a service? Here are the steps.Create the service class, define the metadata with the decorator,and import what we need. Look familiar?These are the same basic steps we followed to build our components andour custom pipe. Let’s look at the code for a simple service.Here is the class. We export it so this service can be used from anyother parts of the application. This class currently has one method, getProducts.This method returns an array of products.Next we add a decorator for the service metadata.When building services we often use the injectable decorator.This decorator is only really required here if the service itself hasan injected dependency; however, it is recommended that ever serviceclass use the injectable decorator for clarity and consistency.Lastly, we import what we need. In this case, injectable.Now let’s build our service.I’ve opened the folder for the sample application in the editor once again.Since our service will only provide product data, we’ll add it to theproducts folder. We’ll create a new file and call itproduct.service.ts to follow our naming conventions.We’re then ready to create the service class.I bet you can do it in your sleep by now.Export, class, and the class name.Since the service provides products, we’ll call it ProductService.Next we decorate the class with the injectable decorator and we’lladd the import statement for that decorator.As we discussed earlier, this decorator is optional unless the servicehas an injected dependency of its own, but it is good practice to addit to every service so we added it here.Now that we have the structure in place we can add properties ormethods to the class as needed. Unless marked private or protected,the properties and methods defined in the class are accessible to anyclass that uses this service.For our product service we want a getProducts method that returns thelist of products. We strongly type this return value using ouriProduct interface so we need to import this interface.In the next module we’ll see how to retrieve the products using HTTP.For now we’ll hard code them in here.If you’re coding along, feel free to copy some products from theproducts.json file in the API products folder.Notice that we have no properties defined in this class so we are notusing this particular service to share data.We are using it to encapsulate the data access features.By using this service to provide the list of products, we take theresponsibility for managing the data away from the individual component.That makes it easier to modify or reuse this logic.So we’re done with our service for now. How do we use it?Well, the service is just really an ordinary class until we registerit with an Angular injector. Let’s do that next.
Registering the Service
As illustrated in this diagram, we register the service with anAngular injector and the injector provides the service instance to anyclass that defines it as a dependency, so what’s actually involvedwith registering a service with the injector?To register a service we must register a provider.A provider is code that can create or return a service, typically theservice class itself. How do we register a provider?We define it as part of the component or Angular module metadata.If we register a provider in a component’s metadata, the Angularinjector can inject the service into the component and any of itschildren so we should take care to register the provider at theappropriate level of the application component tree.If we register a provider in an Angular module, the servicesregistered with the Angular injector at the application’s root, makingthe service available everywhere in the application.We’ll talk more about registering a service provider in an Angularmodule when we cover Angular modules in detail later in this course.For now, we’ll focus on registering a service with a component.If we register the provider for the product data service in theproduct list component, the Angular injector can inject the serviceinto the product list component and any of its children.It could not inject the service into the product detail componentunless we register the provider again in the product detail component.Note that if we did register the provider for the service twice,we would no longer have a singleton.The Angular injector would manage two instances of the service.One for the product list component and its children, another for theproduct detail component and its children.If instead we register the provider in the root app component,the Angular injector can inject the service into any component of the application.Since we know the product detail component will also need the productdata service, let’s register it at the root.Here is the app component we built early on this course.To register a provider that creates our service, we add the provider’sproperty to the component decorator.The provider’s property is an array so we could register multiple providers.To register a provider for our product service, we specify productservice here and import it here. Let’s do that now.Here is the app component. In the metadata, we’ll add the provider’sproperty and specify our product service.So we of course need to import our product service.An instance of the product service is then available for injection inthe app component or any of its child components.Now we can specify where we need this service to be injected.
Injecting the Service
Here again is our diagram. In the last clip we saw how to registerthe service with the Angular injector.Now we just need to define it as a dependency so the injector willprovide the instance in the classes that need it.So how do we do dependency injection in Angular?Well, the better question is, how do we do dependency injection in TypeScript?The answer is in the constructor. Every class has a constructor thatis executed when an instance of the class is created.If there is no explicit constructor defined for the class, an implicitconstructor is used, but if we want to inject dependencies such asan instance of a service, we need an explicit constructor.In TypeScript a constructor is defined with a constructor function.What type of code normally goes into the constructor function?As little as possible. Since the constructor function is executedwhen the component is created, it is primarily used for initializationand not for code that has side effects or takes time to execute.We identify our dependencies by specifying them as parameters to theconstructor function like this.Here we define a private variable to hold the injected service instance.We create another variable as the constructor parameter.When this class is constructed, the Angular injector sets thisparameter to the injected instance of the requested service.We then assign the injected service instance to our local variable.We can then use this variable anywhere in our class to access serviceproperties or methods. This is such a common pattern that TypeScriptdefined a shorthand syntax for all of this code.We simply add the accessor keyword such as private here to theconstructor parameter. Then this is a shortcut for declaring thisvariable, defining a parameter, and setting the variable to the parameter.Neat! You’ll see this technique used throughout the Angulardocumentation and other code examples.Ready to give it a try? We want to use our service to get products inthe product list component so we’ll define our product service as adependency in the product list component.We don’t have to add the providers array here because the productservice is already registered in the app component, which is theparent of this component. All we need is a constructor and we alreadyhave one here. We’ll use the shorthand syntax to define thedependency, private_productService. We use an underscore here todenote that this is a private variable.Then because we are using TypeScript we type colon and the type,which is product service. Note that the accessor doesn’t have to private.The shorthand syntax works with public and protected as well.So now we have a syntax error here. I bet you know why.Yes, we need to import product service so we can use it as the datatype here. Now when an instance of the product list component iscreated, the Angular injector injects in the instance of the product service.We are at the point now where we can actually use the product service.First, let’s delete the hard-coded products from here.We’ll instead get them from the service.Now the question is, where should we put the code to call the service?One thought might be to put it in the constructor, but ultimately ourproduct service will go out to a backend server to get the data.We don’t want all of that executed in the constructor.Other thoughts? Remember our discussion about lifecycle hooks?Earlier in this course we said that the OnInit lifecycle hook providesa place to perform any component initialization and it’s a great placeto retrieve the data for the template.Let’s use the OnInit lifecycle hook.We want to set the product’s property to the products returned fromour service. To call the service we use our private variablecontaining the injected server instance.We then type a dot and the name of the method we want to call.Notice how IntelliSense helps us with all of this.There is a small problem with our code at this point.Since the constructor is executed before the ngOnInit, the list ofproducts will be empty here. We want to set our filtered list ofproducts to this list of products so we need to move this line of codeto the ngOnInit as well. Let’s make one more little change.Let’s remove the default list filter value so we’ll see all of theproducts in the list. We should be all set to see our result in thebrowser and here are our products. Yay!Notice that we have more products displayed now because I hard-codedmore products into the service.Let’s finish up this module with some checklists we can use as webuild our services.
Checklists and Summary
We build a service using the same techniques as when we buildcomponents and custom pipes. We start by creating the service class.We specify a clear class name appropriate for the services it provides.Use PascalCasing where each word of the name is capitalized.Append service to the name and don’t forget the export keyword.We then decorate the service class with the injectable decorator.Don’t forget the app prefix and since the decorator is a function,follow it with open and closing parentheses.This particular decorator is not always required, but it is a goodpractice to add it. And be sure to define the appropriate imports.We can register a service in a component or in an Angular module.We’ll talk more about registering services in Angular modules later inthis course. When using a component, the first step to registering aservice is to select the appropriate level in the component hierarchythat the service should be registered.Use the root app component if the service is shared throughout the application.If only one component needs the service, register it directly withinthat component. Otherwise, select a common ancestor of the componentsthat need the service. In the selected component metadata, use theproviders property to register the service.Pass the service provider as an element of an array and be sure todefine the appropriate imports.In any class that needs the service, specify the service as a dependency.Use a constructor parameter to define the dependency.The Angular injector will inject an instance of the service when thecomponent is instantiated.This module was all about services.We began with an overview of how services and dependency injectionwork in Angular. Then we walked through how to build a simple service.We defined how and where to register the service with Angular and weexamined how to define the service as a dependency so the serviceinstance is injected into any class that needs it.In this module we built the product data service and registered itwith the app component. So our product list component no longer hashard-coded products.Next up, we’ll see how to modify the service to retrieve data using HTTP.
Retrieving Data Using HTTP
The data for our application is on a server somewhere in the cloud,at the office, under our desk. How do we get that data into our view?Welcome back to Angular: in this module we learn how to use HTTPwith observables to retrieve data.Most Angular applications obtain data using HTTP.The application issues an HTTP get request to a web service.That web service retrieves the data, often using a database andreturns it to the application in an HTTP response.The application then processes that data.In this module we begin with an introduction to observables and thereactive extensions. We then examine how to send an HTTP request andmap the result to an array. We add some exception handling and welook at how to subscribe to observables to get the data for our view.We finished the first cut of a product data service in the lastmodule, but it still has hard-coded data.Now we’ll replace that hard-coded data with HTTP calls.Let’s get started.
Observables and Reactive Extensions
Sending an HTTP Request
We often encapsulate the data accessed for our application into a dataservice that can be used by any component or other service that needs it.In the last module we did just that, but our product data servicestill contains a hard-coded list of products.We instead want to send an HTTP request to get the products from abackend web server. Angular provides an HTTP service that allows usto communicate with a backend web server using the familiar HTTPrequest and response protocol. For example, we call a get method ofthe HTTP service, which in turn sends a get request to the web server.The web server response is returned from the HTTP service to ourproduct data service as an observable.What does this look like in code?This is the product service we built in the last module, modified toretrieve the products using Angular’s HTTP service.Let’s walk through this code. First, we specify a URL to the productson the web server. This defines where we send our HTTP requests.Note that this URL is shown for illustration purposes only and is nota real URL. Next we add a constructor.Recall from the last course module that we use a constructor to inject dependencies.In this case we need Angular’s HTTP service so we inject it here.Recognize this syntax? It creates a private _http variable andassigns the injected service instance to that variable.And since we are strongly typing this variable to HttpClient,we import HttpClient from the @angular/common/http package here.As a side note, we had mentioned earlier that in some cases theinjectable decorator was optional.Now that our product service has an injected dependency,the injectable decorator is required.Recall also from the last course module that before we can inject aservice in as a dependency, we need to register that service’sprovider with Angular’s injector.The HTTP service provider registration is done for us in theHttpClientModule included in the @angular/common/http package.To include the features of this external package in our application,we add it to the imports array of our application’s Angular module @module.Recall that the declarations array is for declaring components,directives, and pipes that belong to this module.The imports array is for pulling in external modules.Now our Angular module illustration looks like this.We declare our components, we declare the directives and pipes thatthose components require, and we import the external modules that we need.Going back to the product service, in getProducts we use the injectedHTTP service instance and call the get method, passing in the desired URL.The HTTP service then sends a get request using the specified URL.Often, the data returned from the backend server is in JSON format.Lucky for us, the HttpClient get method makes it easy to receive thatJSON data. We specify the expected type of response by setting theget method’s generic parameter.Since we are expecting an array of product objects, we set the genericparameter to IProduct array. The get method then automatically mapsthe response object returned from the backend server to the definedtype so we don’t have to. Does this generic syntax look familiar?We used it earlier in this course to define the event payload whenpassing event information from a nested component to its container.We aren’t quite finished. What does our method now return?Since we are using strong typing, we should have a function returnvalue here. We define the get method generic parameter as IProductarray so will that be what we get back? Not quite.The getProducts method returns an observable of IProduct array.That’s because the HTTP calls are asynchronous operations and it’simportant to note that HTTP calls are single asynchronous operations,meaning that the observable sequence returned from the get methodcontains only one element. This element is the HTTP response objectmapped to the type specified in the generic parameter.Notice that the observable also takes advantage of generics to definethe type of data it is observing in the observable sequence.In our case it’s the array of products.Now let’s add HTTP to our product service.We are looking at our application’s Angular module we called @module.Recall from the slides that Angular registers its HTTP serviceprovider in an Angular module called HttpClientModule.In our application’s Angular module we import that HttpClientModule.We then pull that module into our application by addingHttpClientModule to the imports array here.Now we can inject the Angular HTTP service into any class that needs it.Here is the product data service we created in the last module withall of the hard-coded data. We want to modify our product serviceto get the product data using HTTP.Let’s start at the top with the import statements.We import the HttpClient service and we import observable fromrxjs/Observable. We want Angular to provide us an instance of theHttpClient service so we identify it as a dependency in the constructor.We don’t have a constructor yet so let’s add that first.Then we specify the parameter. Angular will then inject theHttpClient service instance into this variable.Now we need to identify the location of our web server.Hmmm. This doesn’t look like a valid URL to a web server and to keepthings simple, the demonstration reads the data from a local JSON filethat was provided with the starter files.That way we don’t need to set up an actual web server.To change this code to work against a web server, simply change thisURL to point to an appropriate web server and of course you need towrite the server-side code to return the list of products.Ah, it’s finally time to delete our hard-coded data.So let’s delete the hard-coded products from the getProducts method.Gone. We’ll call the http.get method here instead, passing in thedefined URL. Since we expect the response to be a JSON structurecontaining an array of products, we set the get method genericparameter to IProduct array. When we get a response back, this methodwill then automatically map the returned response to an array of products.We’ll need to change the return type as well.Now this method returns an observable of IProduct array.We can’t try this out at this point because we are not yet subscribingto the observable returned from this service.Let’s add some exception handling first, then modify the product listcomponent to subscribe to the observable list of products.
Subscribing to an Observable
If you are familiar with promises, you know that you received theresult of the promise, x in this illustration, by calling then.Then takes two arguments. A value function that is called when thepromise completes successfully and an error function to handle anyerror condition. If we define x as an observable instead, we simplyreplace the then with subscribe.Since observables handle multiple values over time, the value functionis called for each value the observable emits.In some cases we want to know when the observable completes.So observables provide an optional third handler that is executed on completion.The subscribe function returns a subscription.We could use that subscription to call unsubscribe and cancel thesubscription if needed. Now that our product data service isreturning an observable, any class that needs product data such as ourproduct list component, can call our service and subscribe to thereturned observable like this. As we stated earlier, observables are lazy.An observable doesn’t start emitting values until subscribe is called.So this line of code calls the product data service getProducts methodand kicks off the HTTP get request.It is then set up to asynchronously receive data and notificationsfrom the observable. The first function passed to the subscribemethod specifies the action to take whenever the observable emits an item.The method parameter is that emitted item.Since HTTP calls are single async operations, only one item isemitted, which is the HTTP response object that was mapped to ourproduct array in the service so the parameter is our array of products.This code then sets the local products property to the returned arrayof products. The second function is executed if the observable fails.In this example, it sets a local error message variable to thereturned error. A third function not used here, specifies the actionto take when the observable ends with the completed notification.The third function is rarely used when working with HTTP requestssince they automatically complete after emitting the single responseand we aren’t using the returned value here since we have not providedan option for the user to cancel the request.Let’s give this a try.Here in the product list component we see a syntax error.Type observable of IProduct array is not assignable to IProduct array.Now that we’ve changed the product service to return an observable,we cannot assign the result to our product property directly.Rather, we subscribe to the returned observable.When the observable emits the data, we set our product property to thereturned array of products, but things don’t always go as expected.To handle any errors, let’s add an error message property.If our request for products fails, our error message property is setto the error. What is this any syntax?This is a casting operator. We are casting the error returned fromthe observable to the any data type. Are we ready to try it out?Oh, we have no data. Why is that? Let’s look again at our code.Recall that we said that HTTP is an asynchronous operation.What does that mean exactly for this code?Let’s take it by the numbers. Angular first initializes the componentand executes the ngOnInit method. We call the getProducts method ofthe product service. The product service returns an observable ofIProduct array. We subscribe to that observable and the HTTP getrequest is submitted. This is the asynchronous operation.This code is then complete and we execute the next line, which issetting our filtered products, but at this point, our productsproperty is not yet set. So the filtered products is empty and we seeno data. At some future point in time the service receives the HTTPresponse from our request. The response data is mapped to an array ofproducts and the observable emits that map data to any subscribers.Our subscriber receives the emitted data and assigns our productproperty to the emitted array of products, but since we are binding tothe filtered products property, we are not notified that we now havethe retrieved list of products.There are several ways we can handle this.One option is that we can move this line into the subscribe function.That way we won’t assign the filtered products until the retrieved setof products are emitted from the service.Right now the first argument passed into the subscribe method is asingle-lined function. To pass in a multiple-lined function we needto add curly braces like this. Then we can add additional lines intothe function like this line. Now our filtered products property isset after the products property is set to our list of products.Let’s check it out. There are our products. Success!We have more products here now because we are retrieving them from theprovided product.json file. Sweet!Remember the do we added to the HTTP get pipeline?It displays the retrieved data. If we open the F12 developer tools,we see that data in the console here.So the recommended way to use HTTP is to encapsulate it in a servicelike our products service, then expose an observable for use by anyclass that needs product data. The class simply subscribes to theobservable and waits for data or a notification.Let’s finish up this module with some checklists we can use as we workwith HTTP and observables.
Checklists and Summary
Before we can use Angular’s HTTP client service, some setup is required.We need to ensure that the service provider is registered with theAngular injector. This registration is done for us in theHttpClientModule so all we need to do is pull the HttpClientModuleinto our application. We do this by adding HttpClientModule to theimports array of one of our application’s Angular modules.Build a data access service to wrap HTTP requests.In that data service, specify the needed imports, define a dependencyfor the Angular HTTP client service using a constructor parameter.Create a method for each HTTP request.In the method, call the desired HTTP method such as get and pass inthe URL to the desired server. Use generics to specify the responsereturn type. This will transform the raw HTTP response to thespecified type. And do error handling as desired.In any class that needs data from a data service, call the subscribemethod to subscribe to the observable.Provide a function to execute when the observable emits an item.This often assigns a property to the returned JSON object and if thatproperty is bound to a template, the retrieved data appears in the view.And add an error function to handle any returned errors.This module was all about HTTP and observables.We began with an overview of observables and reactive extensions.We examined how to build a data access service that sends requestsfor data over HTTP. We walked through how to set up some basicexception handling and we saw how to subscribe to the returnedobservable and ultimately display the resulting data in the view.For more information on using HTTP with an Angular application,including create, read, update, and delete or CRUD operations,see the Angular: Reactive Forms course.It demonstrates how to display, edit, and save data in Angular.For more information on observables and rxjs, see this Play by Play course.We’ve now removed the hard-coded from the product data service, yay!And instead retrieved the data using HTTP.In our sample application we are using HTTP to retrieve the data froma local JSON file, but the techniques are the same for retrieving datafrom a backend service.Next up, we’ll see how to display multiple pages with navigation and routing.
A single view does not an application make.Welcome back to Angular: in these next two modules we defineroutes to navigate between multiple views in our application.Users like to have all of the information they need at their fingertips.So our applications often provide multiple sets of data, in multiplelayouts, across multiple views. Routing provides a way for the userto navigate between those many views of the application, whether thereare five, 10, or hundreds.In this module we start with an overview of how routing works in Angular.We examine how to configure routes and tie routes to actions.And we define where to place the routed component’s view.Currently our app component embeds our product list component as anested component. We instead want to define a set of routes so theuser can navigate to the welcome view, product list view, or productdetail view. We’ve already built the product list component and I’veprovided the welcome component with the starter files in the GitHubrepository for this course. As part of the demos in this module,we’ll build the shell for the product detail component.When we’re finished with this module we’ll have a simple applicationthat routes to multiple views.
Generating Code and Handling Undefined
Before we jump into routing, we need more components so we havesomething to route to. I provided the welcome component as part ofstarter files. Let’s build the product detail component.The product detail component should ultimately look like this, but wewant to focus on routing, not building another component.So let’s just create a shell for the product detail component so wecan route to it. We could use the explorer and create new componentclass and template files manually, or we could use the Angular CLIto automatically create those files.We are going to spend more time on the CLI later in this course,but if you want to try it out now, start by opening a terminal window.I’ll use the integrated terminal built in to VS Code.If you don’t already have the CLI installed, install it now usingnpm install -g for global, @angular/cli.I already have it installed so won’t install it again.Next we type ng for the Angular CLI, g for generate, c for component,and the name of our component. Since we want to create this componentunder the products folder, we add the path to the desired componentname, products/product-detail.component following our naming convention.That’s all that is required. By default, however, Angular will createa new folder for this component. For this sample application we wantthe contents of our product folder to be flat.We’ll use the –flat option to achieve this.We’ll learn much more about the Angular CLI later in this course.For now, press Enter and the Angular CLI creates the component filesfor us and it updated our Angular module. Yay!We can see here in the explorer that it created the style sheet in aCSS file, the template in an HTML file, and the class in a TypeScript file.It even created the start of a unit test for us.Let’s check out the generated template. Not much here.We’ll replace the generated HTML with some placeholder text and useinterpolation to bind to a page title.Here we include the product’s name in that title.If we retrieve the product to display using HTTP, which we most likelywill, we could have a problem with this code.Any idea what could go wrong here? Recall from the last module thatHTTP is asynchronous. This means that our page could attempt todisplay the product’s name before the product is retrieved.At that point, the product property is undefined so we would get aruntime error telling us it can’t read the property product name of undefined.How do we ensure this error doesn’t happen to us?There are several common ways to prevent undefined property errors.We could use the safe navigation operator defined with a question mark.The safe navigation operator guards against null and undefined valueswhen navigating an object’s properties.If the product object is null or undefined, the safe navigationoperator simply returns null and does not attempt to access theproduct name property. Hence we don’t see an undefined property error.The safe navigation operator is great, but it is not always the best option.For example, it does not work with used with the ngModel two-way binding.It can also be quite tedious when we display many properties like inour detailed template. So there is another option.We can use ngIf and check for the existence of the product object.We add the ngIf to an HTML element that encloses all references tothe product object. Then we don’t need to use the safe navigation operator.Next, let’s look at the TypeScript file.The generated component class has all of the basic syntax in place.All it needs is the page title and product properties that we arereferencing in the template. Notice that the CLI generated theselector property here. The selector property is only required if thecomponent will be nested within another component.We won’t need to nest this component; we’ll instead display thecomponent’s view as part of the routing, so let’s delete the selector.Now let’s check out the Angular module.Notice that the CLI added the appropriate import and declared our new component.Very nice. Every time we add a component to the application, we needto declare the component in an Angular module.We currently have only one Angular module, @module, so the productdetail component and the welcome component must be added to thedeclarations array for the AppModule.If we use the Angular CLI as we did in this example, it automaticallyadds the appropriate declarations. Cool!If we don’t use the CLI, like for our welcome component, we need toadd the component to the declarations array ourselves.Let’s do that now. We add the welcome component to the declarationsarray, then add the associated import statement.Now that we have the basic components in place, we are ready to addrouting to our application.
How Routing Works
An Angular application is a single page application.That means all of our views are displayed within one page, normallydefined in the index.html file. So each of the 5, 10, or 100s ofviews take turns appearing on that one page.How do we manage which view to display when?That’s the purpose of routing. We configure a route for eachcomponent that wants to display its view on the page.As part of our application design, we provide a menu, a toolbar,buttons, images, or data links that allow the user to select the viewto display. We tie a route to each option or action.When the user selects the option or performs the action,the associated route is activated.Activating a component’s route displays that component’s view.So for example, the user selects a menu option to display the product list.The product list route is activated and it displays its view.Hmmm. Let’s look at that process again with an illustration.Here is the menu that we’ll add to our sample application.We tie a route to each menu option using a built-in router directivecalled router link. When the user clicks on the product list optionfor example, the Angular router navigates to the products route.The browser’s location URL changes to match this past segment and wesee /products appear in the address bar.By default, Angular uses HTML 5 style URLs, which don’t require thehash symbol to indicate local navigation.By using the HTML 5 style URLs, you need to configure your web serverto perform URL rewriting. How this is done depends on your web server.See the documentation for your web server on how to configure URL rewriting.Angular also supports hash style routing, which does not require URL rewriting.We’ll look at how to use hash style routing later in this module.When the browser’s URL changes, the Angular router looks for a routedefinition matching the past segment, products in this example.The route definition includes the component to load when this routeis activated. In this case, the product-list.component.The Angular router then loads the component’s template.Where does it display this template? Where we specified with thebuilt-in routing directive called router-outlet and the product list appears.So that’s how routing works. We’ll examine these steps in furtherdetail and try them out in demos as we journey through this course module.
Routing is component based so we identify the set of components thatwe want to provide as routing targets and define a route for each one.Let’s see how this is done. An Angular application has one routerthat is managed by Angular’s router service and we know that beforewe can use a service, we need to register the service provider in anAngular module. Similar to the HTTP module, Angular provides a routermodule in the Angular router package that registers the router service provider.To include the features of this external module in our application,we need to add it to the imports array of our application’s Angular module.In addition to registering the service provider, the router modulealso declares the router directives.In the last clip we mentioned two router directives, router link androuter outlet. By importing the router module, our componenttemplates can use these or any other router directives.RouterModule also exposes the routes we configure.Before we can navigate to a route, we need to ensure that the routesare available to the application.We do this by passing the routes to RouterModule, like this.We call the RouterModule’s forRoot method and pass our array of routesto that method. This establishes the routes for the root of our application.If we want to use hash style routes instead of HTML 5 style routes,we change this code to set useHash as shown here.With that we are ready to configure some routes.The router must be configured with a list of route definitions.Each definition specifies a route object.Each route requires a path. The path property defines the URL pathsegment for the route. When this route is activated, this URL pathsegment is appended to the URL of our application.The user can type in or bookmark the resulting URL to return directlyto the associated component’s view.In most cases we also specify a component, which is the componentassociated with the route. It is this component’s template that isdisplayed when the route is activated.These are all examples of route definitions.The first route simply maps the specific URL path segment to aspecific component. So this URL displays the template from theProductListComponent. The :id in the second route represents a route parameter.The product detail page displays the detail for one product so itneeds to know which product to display.The ProductDetailComponent reads the id from this path segment anddisplays the defined product. We can define any number of parametershere separated with slashes. What does this route do?Yes, this URL displays the template from the welcome component.This one defines the default route.The redirect here translates the empty route to the desired defaultpath segment, in this example, the welcome route.A redirect route requires a path match property to tell the router howto match the URL path segment to the path of our route.We only want this default route when the entire client-side portion ofthe path is empty so we set the path match to full.The asterisks in the last route denote a wildcard path.The router matches this route if the requested URL doesn’t match anyprior paths defined in the configuration.This is useful for displaying a 404-not found page or redirecting toanother route. A few things to note here.There are no leading slashes in our path segments and the order ofthe routes in this array matters.The router uses a first match wins strategy when matching the routes.This means that more specific routes should always be before lessspecific routes such as the wildcard route.Ready to try this out?We are back in the sample application with the index.html file open.The first step to set up routing is to define a base element in thehead tag of the index.html file. Notice that the Angular CLI alreadydid that for us here. This element tells the router how to composethe navigation URLs. Since the app folder is the app root, we’ll setthe href for the base tag to slash.Now we are ready to configure the route definitions.For that we go to our Angular module.Add the appropriate import statement, then add router module to theimports array. This registers the router service provider, declaresthe router directives, and exposes the configured routes.How does the router module know about our configured routes?We pass them into the router module by calling the forRoot method.We then configure the routes here by passing them in using an array.Let’s start with the product routes.For each route we specify the path and a reference to the component.The template defined in this specified component will display when therouter navigates to this path.Next we add the route to display our welcome page.We’ll set the path to welcome and specify the welcome component.When the application loads, we want to default to the template fromthe welcome component so we’ll specify a default route that redirectsto our welcome component and let’s define a wildcard path in case therequested URL doesn’t match any prior paths defined in the configuration.This is often used for displaying a 404 not found page, but in oursimple example, we’ll use it to redirect back to the welcome page.There’s a lot of stuff here now in our root application module.In a later course module, we’ll look at how to refactor this moduleinto multiple Angular modules for a separation of concerns.
Tying Routes to Actions
With routing, the user can navigate through the application in several ways.The user can click a menu option, link, image or button that activatesor navigates to a route. The user can type the associated URL segmentin the address bar after the application URL or use a bookmark to thatURL or the user can click the browser’s forward or back buttons.The route configuration handles the URLs so the last techniques willjust work. We need to handle the first technique by tying routes tothe user actions. We need to decide how we will show the routingoptions to the user. We could display a navigation pane with links.We can provide a toolbar or images or we can build a navigation menulike this one. In a more full-featured application, the menu couldhave many more options and sub options, but this will do for our purposes.We define that menu as part of this component’s template.We then need to tie a route to each menu option.We do that using the router link directive.The router link is an attribute directive so we add it an element suchas the anchor tag here and we enclose it in square brackets.We bind it to a template expression that returns a link parameters array.The first element of this array is the string path of a route.Additional elements can be added to this array to specify optionalroute parameters. The router uses this array to locate the associatedroute and build up the appropriate URL based on any provided parameters.When the user selects the option, the associated route is activated.Activating a component route displays that component’s view.Now let’s add a menu and use the router link directive so the user cannavigate to the views in our sample application.First, we need to decide how to show the routing options to the user.For our sample application we’ll build a menu.We want to add that menu at the root of our application so we’ll addit to the app component. In the app component template currentlywe’re nesting the product list component.Now that we are implementing routing we will route to the product listcomponent instead. That means that it no longer needs a selector.In the product list component let’s remove that selector.Going back to the app component, we’ll replace the nesting with anavigation menu. This menu uses the nav element and the navbarclasses from the Twitter Bootstrap styling framework.Let’s see how this looks in the browser.Here is our new menu, but clicking on the menu options don’t doanything yet and our product list no longer appears.We need to tie routes to these menu options.We’ll use the router link directive to tie a route to each of thesemenu options. For the home menu option we’ll add the router link tothe anchor element, but we could use any clickable element.We want to tie the welcome route to the home menu option so we specifywelcome here. Pay close attention to this syntax.We assign the router linked directive to an array defined within quotes.The first element of the array is a string so it is also enclosed in quotes.We’ll use similar syntax to tie the products route to the product listmenu option. Now we just need to tell Angular where to place ourviews and display the routed component’s template.
Placing the Views
When a route is activated, the associated component’s view isdisplayed, but displayed where? How do we specify where we want therouted component to display its view?We use the router outlet directive.We place that directive in the host component’s template.The routed components view then appears in this location.Let’s add the router outlet to our sample application.We are back looking at the app component because it is the host forour router. We add the router outlet in the template where we want todisplay the routed component’s view. We’ll put it here.Whenever a route is activated, the associated component’s viewdisplays here. Let’s see how that looks in the browser.Oh my! Where did that page come from?That’s the welcome page provided in the starter files.When the application launches, the default route is activated and thewelcome view displays. If we click on the product list menu,the router link directive now activates the product list route and theproduct list view appears. Sweet! Our application component can nowroute to multiple views. Notice the URL.The URL segment we defined for the route is displayed here.If we type in something like welcome, the welcome component’s view is displayed.Now that we have our routing in place, let’s review how these routingfeatures work together. When the user navigates to a feature tied toa route with a router link directive, the router link uses the linkparameters array to compose the URL segment.The browser’s location URL is changed to the application URL plus thecomposed URL segment. The router searches through the list of validroute definitions and picks the first match.The router locates or creates an instance of the component associatedwith that route. The component’s view is injected in the locationdefined by the router outlet directive and the page is displayed.We now have basic routing in our sample application. Yay!As we’ve seen in this course module, routing is rather intricate,requiring code in multiple files and strings such as parameter namesand route paths that must match across those files.So let’s finish up this module with some check lists that can helpensure all of the bits of routing are in the right places.
Checklists and Summary
To route or to nest. That is the question.When creating components we need to think about how they will be displayed.For components designed to be nested within other components we needto define a selector as part of the component decorator.The selector provides the name of the directive and then we nest thecomponent within another component using a directive to define wherethe component template appears. The component does not then need a route.For components designed to be displayed as a view within our singleapplication page, the component needs no selector, but we do need toconfigure routes. We then tie those routes to actions and actionactivates a route to display the view.If we want to do routing in our application, we need to configure theroute definitions, tie routes to actions, and place the view.Let’s do check lists for each of these tasks.The first step for doing routing in an application is to configure the routes.Begin by defining the base element in the index.html file.Add router module to an Angular module’s imports array.Then add each route to the array passed to the router module’s forRootmethod and remember that order matters.The router will pick the first route that matches.Each route definition requires a path, which defines the URL pathsegment for the route. Be sure the path has no leading slash.Use an empty path for a default route and two asterisks for a wildcardroute, which is matched if no prior path matches.Most route definitions also include a component.The component is a reference to the component itself.It is not a string name and is not enclosed in quotes.Once we have the routes configured, we need to tie those routes to actions.First we identify which actions to tie to which routes.Then we add the RouterLink directive as an attribute to any clickableelement in a component’s template.We can use them in menu options, toolbars, buttons, links, images, andso on. Be sure to enclose the router link in square brackets.Bind the router link to a link parameters array.The first element of the link parameters array is the route’s path.All other elements in the array are values for the route parameters.Use the router outlet to identify where to display the routedcomponent’s view. This is most often specified in the host component template.When a route is activated, the route component’s view is displayed atthe location of the router outlet.This module was all about navigation and routing.We began with a look at how routing works.We then walked through how to configure routes, tie routes to actions,and define where the routed component’s view should appear.Our app component had embedded our product list component as a nested component.In this module we were finally able to remove that nesting.We set up routing so we can now navigate to our welcome and productlist components. We’ve covered the basics of routing in this module,but there is so much more.In the next module we’ll look at some additional routing techniquesand add navigation to the product detail component.
Now that we know the basics of routing, we are ready for more.Welcome back to Angular: in this module we look at severaladditional routing techniques.With what we learned in the prior module, a user can now navigate toany defined route in our application, but that only covered the verybasic routing scenarios. What if we need to pass parameters to ourroute or activate a rout with code instead of with a clickable element?Or what if we need to protect a route and only allow access to it inspecial cases or by certain users?Or ask a user to save changes before leaving a route?In this second module on routing, we examine how to pass parameters toa route, how to activate a route with code, and how to protect ourroutes with guards.When we’re finished with this module, we’ll know how to handleadditional routing scenarios including routing to a component thatrequires parameters such as our product detail component.Let’s get started.
Passing Parameters to a Route
Activating a Route with Code
We want to add a back button to our product detail page that navigatesback to the product list page. We could activate this route using therouter link directive in the component template, just like we did withthe menu options, but it’s also possible to route with code.So let’s try that out instead.When would you want to navigate with code instead of the router linkdirective in a template? One example is a safe button where you needto execute some code to save the data and then route.To route with code we use the router service.We import the router service from Angular router.We define a dependency on the router service using a constructor parameter.The router instance is then injected into this component class.Every time we inject a service dependency into a class we should askourselves, hmmm, did we register this service with the Angular injector?In the case of router, it is registered in RouterModule which we addedto our application’s Angular module imports array.We use this router instance to activate a route.Here we define a method that we can call from the template based on auser action. The code uses the navigate method of the router serviceand passes in the same link parameter array we use when binding therouter link. In this example we route to the products route and don’tpass any arguments. Let’s give this a try.Here we are looking at the product detail component.We want the product detail component to navigate back to the productlist component. We define the router as a dependency by addinganother constructor parameter.When this component class is constructed, we’ll get an instance ofboth the activated route service and the router service.Now we can build a method that navigates with code.Since the purpose of this method is to navigate back, we’ll call it onBack.It doesn’t return anything so we’ll set its return type to void.In this method we use the this._router instance and call the navigate method.We pass it a link parameters array.In this example we want to navigate back to the product list componentand we don’t need any parameters.We just define the route path, which is products.In the product-detail template we’ll add a button.We again use the Twitter Bootstrap Style classes to give the buttonsome style. We use event binding to bind the click event of thebutton to the onBack method we defined in the class.Now let’s check it out in the browser.Click on the menu option to display the product list, then click on a product.The product detail page is displayed.We click our back button and we are back on the product list page.Let’s try another one. We see the detail page.Now we’re back on the product list page.Our code based navigation is working.So routing with code involves importing the router and using itsnavigate method to activate the route.Now that we have several routes in place, let’s look at how to protectthem with guards.
Protecting Routes with Guards
There may be times that we want to limit access to a route.We want routes only accessible to specific users such as anadministrator for example, or we want the user to confirm a navigationoperation such as asking whether to save before navigating away froman edit page. For that we use guards.The Angular router provides several guards including CanActivate toguard navigation to a route, CanDeactivate to guard navigation awayfrom the current route, Resolve to pre-fetch data before activatinga route, and CanLoad to prevent asynchronous routing.In this clip we work through how to implement the CanActivate guard.You can use the same techniques we’re covering here to implement anyother type of route guard.We’ll build a guard that prevents navigation to the product detailroute unless a specific condition is true.Building a guard clause follows the common pattern used throughout Angular.Create a class, add a decorator, and import what we need.Here we define a guard class. Since we are implementing this guardas a service, we use the injectable decorator and we import what we need.This class implements CanActivate.To create one of the other kinds of guards, change this to implementone of the other guard types. We then implement the canActivate method.For simple cases this method can return a Boolean value, true toactivate the route and false to cancel the route activation.For more complex cases, we could return an observable or a promisefrom this method. Because the guard class is a service, we need toregister the service provider with Angular’s injector.Unlike other services, however, the guard’s service provider must beprovided at the Angular module level.By providing the service at the module level, the router can use theseservices during the navigation process.So in this example we register it in our AppModule by adding it to theproviders array. Using a guard is simple.We built the guard to protect the product detail route so we add theguard to the product detail route.We add canActivate and set it to an array containing the guards toexecute before this route is activated.In our case, there is only one. Let’s give this a try.We want to build a guard that prevents navigation to the productdetail component if the provided URL parameter is not valid.Recall that the route definition for the product detail componentincludes an id, but there is nothing here that defines that this idhas to be numeric or greater than 0, so our guard should preventnavigation to the product detail route is the id is 0 or not a number.Our first step is to build our guard service.We could build it manually, but why not use the Angular CLI?We open the integrated terminal and type ng for the Angular CLI,g for generate, s for service since we’re creating a service thistime, and the name of our service.Since this guard is only for the product detail route, we want it inthe products folder so products/product-guard.service.That’s all that is required, but by default the Angular CLI won’tregister our service. We can tell the Angular CLI to register ourservice into our app module by adding -m for module, app.module, whichis our module file name. Press Enter and we see that the CLI createdthe service and the start of a unit test for that service, and itupdated our app module as we asked it to. We can see that here.Let’s open the resulting service.The CLI added all of the basic boilerplate here for us. Yay!The purpose of this service is to implement a CanActivate guard.So let’s start by implementing CanActivate and we add its associated import.It looks like we need to fix that up a bit.Now we need to implement the CanActivate method and we’ll return asimple Boolean. What do we want this method to do?We need to check the route URL and ensure that the id passed in is valid.Luckily for us, CanActivate has a parameter that gives us theactivated route snapshot. The activated route snapshot contains theinformation about a route at any particular moment in time.Now I’ll paste the code for the method body and we can talk through it.The product detail route URL is comprised of two segments.Product and the requested id. We only care about the id so we pullthe path from the second element, which is index of 1.The plus here at the beginning converts the URL path string to a number.If the resulting value is not a number or less than 1, we display analert, direct the user to a the product list page, and return false toabort the current operation.Notice that this code is the same code we used to activate our routewith code that we saw in the last clip and as we saw in the last clip,to use the router we need to inject it into the constructor and add itto the imports. Here we return false to abort the current navigationand here we return true to continue activating the route.Now we don’t normally want to display an alert from our application.In a real application we’d route to an error page that would notifythe user of the problem and optionally provide a button for navigatingback to the product list page, but this is good enough for our purposes.Next we need to hook up this guard to the appropriate route.Then we add the CanActivate property to the route definition for theproduct detail component and set it to an array.In the array we specify each guard we want to execute when activatingthe product detail route. In this case we have only one.That should do it. Let’s give it a try.If we view the product list page and select a product, our URL isvalid and we navigate to the page.If we instead type any URL that is not a number, we see our message.The product detail route navigation is cancelled and we are redirectedto the product list page. It works.Use route guards any time you want to prevent access to a route,confirm navigation away from a route, or preload data for a route.So let’s finish up this module with some checklists.
Checklists and Summary
We can pass any number of parameters to a route separated by slashes.Add the parameter to the route configuration path by specifying aslash, a colon, and the parameter name.Pass the parameter value by adding it to an element of the linkparameters array bound to the router link directive.Read the parameter value in the navigated component using theactivated route service. Notice here that the parameter name, idin this example, is exactly the same as in the route definition.To activate a route with code, use the router service, be sure toimport the service and define it as a dependency on the constructor.Create a method that calls the navigate method of the router serviceinstance and pass in the link parameters array.Add a user interface element and use event binding to call the created method.We can use guards to prevent access to a route, confirm navigationaway from a route, or to preload data for a route.To create a route or guard we build a guard service.Implement the guard type, in our case CanActivate, and create theassociated method. We then register the guard service provider,which must be registered in a module, not a component.Lastly, we add the guard to the desired route.In this module we covered some additional routing techniques includingpassing parameters to a route, activating a route with code, andprotecting routes with guards, but we’ve only just touched on the basics.If you are interested in learning more about routing, check out myAngular Routing course here .You’ll learn how to pass required, optional, and query parameters ona route; how to fetch data with route resolvers; how to define childand secondary or named router outlets; and more on router guards.Plus you’ll see how to improve your application performance with lazy loading.We now have routing to our product detail component. Yay!However, the product detail component and its associated template arenot finished. We only wired up the bare minimum to demonstrate routing.As a homework assignment, try building the remainder of the productdetail template and code.To check your answer you can find the completed application on myGitHub as described in the First Things First module.There you will also find a version of the product data service thatretrieves one product by id. You’ll need that to get the data for theproduct detail component.At this point our AppModule is looking a little cluttered and hard to manage.Up next, let’s spend some more time with Angular modules and look athow to refactor our application into more manageable pieces.
As we’ve seen throughout this course, Angular modules are a key partof any Angular application.Welcome back to Angular: in this course module we focus onAngular modules and how to use them to better organize our code.Ooh, it’s so beautiful! No, it’s not a Van Gogh, not even a Picassoand yes, it sort looks like a metro map.This is a picture of what our application could look like if weleveraged the power of Angular modules.Instead of one large AppModule like we have now, there are multiplemodules and each piece of our application has a logical place withinone of those modules. This keeps each module smaller and more manageable.In this course module we take another look at the definition andpurpose of an Angular module. We then focus in on the Angular modulemetadata to better understand how to use it.We leverage that knowledge to create a feature module for ourapplication and take it one step further, defining a shared module toreduce duplication. Lastly, we reexamine our application’s rootAngular module. Let’s get started.
What Is an Angular Module?
What is an Angular module? As we’ve seen earlier in this course,an Angular module is a class with an NgModule decorator.Its purpose? To organize the pieces of our application, arrange theminto cohesive blocks of functionality, and extend our application withcapabilities from external libraries.Angular modules provide the environment for resolving the directivesand pipes in our component’s templates.We’ll talk more about this in a few moments.And modules are a great way to selectively aggregate classes fromother modules and re-export them in a consolidated convenience module.Browser module, HTTP module, and router module are all examples of this.And we’ll create our own convenience module when we build a sharedmodule a little later. An Angular module can be loaded eagerly whenthe application starts or it can be lazy loaded asynchronously by the router.Lazy loading is out of the scope of this course, but is discussed indetail in my Angular Routing course here .How does an Angular module organize our application?An Angular module declares each component, directive, and pipe that it manages.Every component, directive, and pipe we create belongs to an Angular module.An Angular module bootstraps our root application component, definingthe component needed to display our first template.An Angular module can export components, directives, pipes, and evenother Angular modules, making them available for other modules toimport and use. An Angular module imports other Angular modules.This brings in the exported functionality from those imported modules.An Angular module can register service providers with the Angularinjector, making the services available to any class in the application.We can think of an Angular module as a box.Inside that box we declare each of our components.If those components need any functionality, that functionality alsoneeds to be defined within this box.The AppComponent sets up the routing for our main menu using routerlink and includes the router outlet directive.So it needs to the routing directives, router service, and routes,which are defined in router module.The ProductList-Component uses ngModel so it needs the FormsModule.The ProductList-Component also uses ngFor and ngIf so it needs thebrowser module. The ProductList-Component uses the pipe so it needsthat too. The ProductList-Component also uses the starRatingcomponents directive so it needs that as well and so on, until thebox contains everything that each of our components needs.Saying this another way, for each component that belongs to an Angularmodule, that Angular module provides the environment for template resolution.The module defines which set of components, directives, and pipes areavailable to the components template.Each declared components template is resolved using only thecapabilities provided within that module.Let’s look at our ProductList-Component as an example.The ProductList-Component’s template uses ngModel so ngModel must beavailable within this module.We achieve that by importing the Angular Forms module.The ProductList-Component’s template also uses a directive we created,the star component so the star component must be available within this module.Since the star component is one we created, we can either declare thestar component within the module directly or we can import anothermodule that exports the star component.Importing an Angular module brings in the functionality exported bythat module and we’d need to do one or the other, never both.We didn’t need to think about template resolution much in our sampleapplication up until now because all of the pieces of our applicationare in one Angular module, but we will need to keep this in mind aswe split our application into multiple Angular modules.Let’s take a quick look at our current AppModule.Here is the Angular module we’ve defined throughout this course.It is the application’s root Angular module and by convention iscalled AppModule. The AppModule imports the system Angular moduleswe need including the router module, which is where we configured our routes.It declares each component and pipe that we created in this course.It registers the service provider for our product detail guard and itbootstraps the application with the root application component,AppComponent. We have a lot of information in here and we’re mixingup basic application pieces such as our welcome component with piecesspecific to our product feature.Let’s journey through the ngModule metadata to better understand howAngular modules work so we can then refactor our AppModule intomultiple modules for better code organization.
As we have seen, every Angular application has at least one Angularmodule called the root application module or AppModule and an Angularapplication has at least one component called the root applicationcomponent or AppComponent. The AppModule bootstraps the AppComponentto provide the directive used in the index.html file.We covered the bootstrapping process in the Introduction to Componentsmodule earlier in this course.The bootstrap array of the ngModule decorator defines the componentthat is the starting point of the application.This is the component that is loaded when the application is launched.Here are some things to keep in mind when using the Bootstrap array.Every application must bootstrap at least one component, the rootapplication component. We do this by simply adding the rootapplication component to the bootstrap array of the root application module.The bootstrap array should only be used in the root applicationmodule, AppModule. As we build other Angular modules we won’t use thebootstrap array.
Every component, directive, and pipe we create is declared by anAngular module. We use the declarations array of the ngModuledecorator to define the components, directives, and pipes that belongto this Angular module. Here are some things to keep in mind whenusing the declarations array.Every component, directive, and pipe we create has to belong to oneand only one Angular module.In our sample application, all of our components are defined in oneAngular module, AppModule. It would be better to divide thecomponents into multiple modules with basic application pieces in theAppModule and feature pieces in an appropriate feature modules.We’ll do that a little later in this course module.As we separate out our pieces, it is important to remember that eachcomponent, directive, and pipe belongs to one and only one Angular module.Only declare components, directives, and pipes.Don’t add other classes, services, or modules to the declarations array.Never re-declare components, directives, or pipes that belong toanother module. This is a corollary to truth #1.If we re-declare then the component, directive, or pipe no longerbelongs to one and only one Angular module.For example, the start component directive belongs to module B.So we should never re-declare star component in module A.We should only declare components, directives, and pipes that belongto this module.All declared components, directives, and pipes are private by default.They are only accessible to other components, directives, and pipesdeclared in the same module.So if we declare the star component in module B, by default thatcomponent is not available to components in other Angular modules.We share components, directives, and pipes by exporting them.We’ll talk more about exporting in a few moments.The Angular module provides the template resolution environment forits components templates. When we include a component in thedeclarations array of an Angular module, the component belongs to thatAngular module. That component’s template directives and pipes arethen resolved within that module.When we use a directive in a component’s template, Angular looks tothe module for the definition of that directive.If the component defining that directive is not declared within thesame Angular module or exported from an imported module, Angular won’tfind the directive and will generate an error.For this example, the star component must be declared in the samemodule as the product list component or the star component must beexported from an imported module, never both.
The exports array of the ngModule decorator allows us to share anAngular module’s components, directives, and pipes with other modules.We can export any of this module’s components, directives, and pipesso they can be pulled in when another module imports this module.We can also re-export system Angular modules such as forms module andHTTP module. We can re-export third-party modules such as material design.Material design is a set of high-quality user interface componentsincluding buttons and dialogs, and we can re-export our own modules.Here are some things to keep in mind when using the exports array.Export any component, directive, or pipe if another component needs it.A module can export any of its declared components, directives, or pipes.Re-export modules to re-export the components, directives, and pipes.This is useful when consolidating features for multiple modules tobuild a convenience or shared module.We can re-export something without importing it first.An Angular module only needs to import the components, directives,and pipes that are required by the components declared in the module.But the Angular module can still provide capabilities to other modulesthat import it by re-exporting.In this example, a shared module exports the forms module, even thoughit did not import it. So any module that imports the shared modulewill have access to the ngModel and other forms directives.We’ll see this in an upcoming demo.Never export a service. Services added to the providers array of anAngular module are registered with the root application injector,making them available for injection into any class in the application,so there is no point in exporting them.They are already shared throughout the application.
An Angular module can be extended by importing capabilities from otherAngular modules. The imports array of the ngModule decorator allowsus to import supporting modules that export components, directives,or pipes. We then use those exported components, directives, andpipes within the templates of components that are declared in this module.Many Angular system libraries are Angular modules such as the formsmodule and HTTP module we’ve used in this course.We can import Angular modules to use their capabilities.Many third-party libraries are also Angular modules such as material design.We can import third-party Angular modules to use their capabilities.We can import our own modules to extend our application withadditional features or share capabilities across several modules.We’ll see that in an upcoming demo, and we could separate out ourroute configurations into its own module or set of modules and import that.Here are some things to keep in mind when using the imports array.Importing a module makes available any exported components,directives, and pipes from that module.Recall that we are using ngModel in our product list component fortwo-way binding. The ngModel directive is exported in the FormsModule.By importing the FormsModule into our AppModule we can use ngModel inany component declared in our AppModule.Only import what this module needs.Only import modules whose exported components, directives, or pipesare needed by this module’s component templates.Don’t import anything this module does not need.Importing a module does not provide access to its imported modules.Hmmm. Let’s look at that with a picture.Here we have AppModule, which declares the product list component,and a shared module that declares and exports the star component.AppModule imports the shared module so the shared module’s exportsare available to the AppModule’s component templates.This means that the product list component can use the star component directive.If the shared module imports FormsModule then the FormsModule’sexports are available to the shared module and the star componentcould use the ngModel directive, but the FormsModule exports are notavailable to the AppModule so the product list component could not usethe ngModel directive. I’ve heard this rule also stated another way.Imports are not inherited. Note, however, that if the shared modulere-exported the FormsModule, then the FormsModule exports areavailable to the AppModule and the product list component could usethe ngModel directive. So when thinking about the relationshipbetween modules, think of a module more as a box than as a tree structure.
Angular modules can also register service providers for our application.The providers array of the ngModule decorator allows us to registerservice providers at the module level.This is similar to the providers array of the component decorator thatallows us to register services at the component level.Recall that at this point our sample application registers the productservice provider at the component level and the product detail guardat the module level. Here are some things to keep in mind when usingthe ngModule providers array.Any service provider added to the providers array is registered at theroot of the application. So the service is available to be injectedinto any class in the application.Say for example we have a feature module called ProductModule.We add the ProductService to the providers array of this module.At first glance we may think we have encapsulated the ProductServiceinto the ProductModule, but that is not the case.Any service provider added to the providers array is registered at theroot of the application and is available to any class, even classesin other feature modules. So if we want to ensure a particularservice is encapsulated and only accessible within a specificcomponent or set of components, add the service provider to theproviders array of an appropriate component instead of an Angular module.Note that this is not the case for lazy loaded services.See the Angular documentation for more information on lazy loading.Don’t add services to the providers array of a shared module.As discussed in the services and dependency injection course module,there should only be one instance of a service that is an applicationwide singleton. So a service should not be included in the providersarray for any module that is meant to be shared.Instead, consider building a core module for services and importing itonce in the AppModule. This will help ensure that the services areonly registered one time. We could even add code to the code modulesconstructor to ensure that it is never imported a second time.See the Angular documentation for details.Routing guards must be added to the providers array of an Angular module.We discussed this in an earlier course module when adding guards to routes.The guard service provider must be defined at the module level so thatthe router can use these services during the navigation process.Now that we’ve covered the basics of the ngModule decorator, let’srefactor our application into multiple Angular modules.
So far in this course we created the root application module,AppModule. It declares all of our components and our pipe.It imports the system Angular modules that our components need.It also registers the routing guard that we built, but this is gettinga little unwieldy. We have no separation of responsibilities.Here we are mixing our basic application features such as the welcomecomponent with our product features such as the product componentswith our shared features such as the star component.As we add more feature sets to this application such as customermanagement, invoicing, and so on, this is only going to get harder to manage.So let’s reorganize and refactor to break this into multiple Angular modules.The first thing we want to do is extract some of these pieces intofeature sets. We can then create a feature module for each feature set.Using feature modules helps us partition our application into logicalgroupings with separate concerns.Our first step is to define a new feature module.Creating a feature module involves defining a new module file,ProductModule in this example, and reorganizing the pieces of theapplication so that all of the associated feature pieces andeverything they need are here in this module.In the declarations array of the feature module we add the appropriatecomponents that provide the features for the application.In this example, we add the product list component and product detail component.Then as we did with the box example at the beginning of this coursemodule, we start to look at what each component needs.In this example, the product list component uses the pipe so we need that.And both the product list and the product detail components use thestar component so we’ll need that here as well, but that’s not enough.The product list component uses ngModel and ngFor and both componentsuse ngIf and routing. How do we get that?We import these needed capabilities from other Angular modules.Our product components use routing so we import the system router module.The product list component uses ngModel so we import the systemFormsModule, and we need ngFor and ngIf.So do we pull in the system browser module? Nope.The browser module should only be imported into the root applicationmodule, AppModule. Instead, we import the system CommonModule.The CommonModule exposes the ngFor and ngIf directives.Not surprisingly, the browser module itself actually imports andexports the CommonModule, which is why we have access to ngFor andngIf when we import browser module in our AppModule.Lastly, we add any related services we want to declare at the modulelevel which make the services available to be injected into any classin the application. In this example we add the ProductService and theProductGuard, which must be at the module level.So even though these module level services are available applicationwide, we include them in the ProductModule and not the AppModule tokeep the code better organized and easier to find.Our feature module is looking pretty good here, but now that we’veremoved these features from the root application module, how will theapplication find all of these features? What’s that?Imports array, did you say? That’s correct.We need to import the ProductModule into the AppModule.That extends the AppModule with the ProductModule features.Want to try this out?
Demo: Feature Modules
We are back in the sample application. Here is our AppModule.Let’s create a new feature module for our product feature.Want to try generating it with the Angular CLI?We open the integrated terminal and type ng for the Angular CLI,g for generate, m for module, and the name of our module.Since we are creating the ProductModule, we want it in the productsfolder so products/product. That’s all that’s required, but bydefault, Angular will create a new folder for this module because itrightly assumes that we’ll create the module when we define thefeature and the feature folder, but we already have the products folder.So we’ll use the –flat option and we want to import this module intothe AppModule to pull in its functionality so we use the -m flag,specifying the module name. Press Enter and we see that the CLIcreated the module. It also updated our AppModule.We can see that here. It added ProductModule to our imports array.Yay! Let’s open the new ProductModule.The CLI already created the class with the ngModule decorator and therequired import statements. Since this module is for our productfeatures, in the declarations array, we add the ProductListComponent,ProductDetailComponent, ConvertToSpacesPipe, and StarComponent, and weneed all of the associated import statements.I’ll fix the quotes and paths off the screen.Now we can remove these declarations from the AppModule.Going back to our ProductModule we can see that the CLI alreadyincluded CommonModule here since we need that in every feature module.We’ll add the FormsModule and RouterModule and their associated import statements.I’ll again fix the quotes and paths off screen.Note that you’ll get a compilation error if you don’t remove the extrapart of these paths. Now we can remove the FormsModule from theAppModule and its associated import statement.When we added the RouterModule to the imports array in the AppModule,we called forRoot to pass in the configured routes for our root component.Now that we are adding the routing module to the imports array of afeature module, we don’t call forRoot.Rather we call forChild and there we pass in the routes related to products.Let’s cut the product routes from the AppModule and paste them here inour ProductModule and we need to import the product detail guard.Recall that the RouterModule registers the router service provider,declares the router directives, and exposes our configured routes,but as we’ve discussed previously, we never want to register a servicemore than once. So when we use forRoot to pass in our configuredroutes, the RouterModule knows to register the router service provider.When we use forChild as we did here, the RouterModule knows not tore-register the router service.Note that we could also consider moving the routes into their own modules.We’ll look at that a little later.Lastly, we add the providers array.We add the product service and product detail guard to that arrayand insert their appropriate import statements.Now we can remove the product detail guard and its import statementfrom AppModule and the product service from the app component’sproviders array. Moving the ProductService to the ProductModule isoptional; we could leave it in the AppComponent’s providers array.Do you think our application will run?And our application works as expected.So we now have our first working feature module.But let’s think about this for a moment.As we build our application, we’ll build more features.Each logical set of features will have their own feature module andeach feature module will most likely need the CommonModule for commondirectives such as ngFor and ngIf, the FormsModule for ngModel andtwo-way binding, and we may have other features that want to reuseour star component. Do we really want to repeat all of this in eachfeature module? There has to be a better way.Yes, we can define a shared module.
The purpose of a shared module is to organize a set of commonly usedpieces into one module and export these pieces so they are availableto any module that imports the shared module.This allows us to selectively aggregate our reusable components andany external modules and re-export them in a consolidated convenience module.Creating a shared module involves defining a new module file,SharedModule in this example, and reorganizing the pieces of theapplication so that the shared pieces are here in this module.First, we add the components, directives, and pipes that we want toshare throughout our application to the declarations array.In this example we only want to add the StarComponent.Then we add to the imports array anything that this shared component needs.In this example we import the CommonModule because our StarComponentmay need it. We don’t import FormsModule because we don’t need it here.If our StarComponent did use two-way binding or we added anothercomponent here that did, we’d need to import FormsModule as well.We then need to export everything that we want to share.The exports array defines what this Angular module shares with anymodule that imports it. We export the StarComponent.That way it is available to the components in any module that importsthe SharedModule. We re-export the CommonModule and FormsModule sotheir directives and other features are available to any module thatimports the SharedModule. And notice here that we can exportsomething without importing it first.To use the SharedModule, we import it into every feature module thatneeds the shared capabilities such as a our ProductModule.Let’s give this a try.We want to build a SharedModule and we’ll again use the CLI.Do you recall the correct CLI command to generate a module?We type ng for the Angular CLI, g for generate, m for module, and thename of our module. Since we are creating the SharedModule, we wantit in the shared folder so shared/shared.We already have the shared folder in place so we’ll specify the –flatoption; that way the CLI won’t create another folder and we want toimport this module into the ProductModule to pull in its functionality.So we use the -m flag, specifying the module path and name.Press Enter and we see that the CLI creates the SharedModule and itupdates our ProductModule. We can see that here.It added SharedModule to our imports array.Let’s open the new SharedModule. The CLI already created the classwith the ngModule decorator and the required import statements and itincluded CommonModule in the imports array here.Now what did we want to share?Well, we want to share the StarComponent so we add that to thedeclarations array here. We’ll fix up that import statement path later.To share the StarComponent we need to export it.Let’s add an exports array and export the StarComponent.There are a few more things that we want to share.So we don’t have to import them into every feature module, we’ll addCommonModule and FormsModule to the exports array.If there were other modules we wanted to share, such as reactiveFormsModule or material design, we could add them here as well.We could also share the convert to spaces pipe.I’ll leave that up to you to add here if you wish.Now we can remove the StarComponent, CommonModule and FormsModulefrom the ProductModule along with their associated import statements.Since these are now already accessible from the imported SharedModule.Are we good to go? Yes! Our application comes up as it did before.Looking back at our code, notice now that our feature module,ProductModule, only contains product pieces and the SharedModule.And the SharedModule is clean only including the pieces we want to share.We can reuse the SharedModule in any future featured modules as we addfunctionality to our application.
We now know that every application has a root application module thatis by convention called AppModule.The main purpose of the AppModule is to orchestrate the application asa whole and now that we’ve removed the feature and shared pieces fromthis module, its purpose is easier to see.Let’s take another look. We’ve reduced the code in AppModule suchthat it now fits on one page. The AppModule normally importsBrowserModule. This is the module that every browser application must import.BrowserModule registers critical application service providers.It also imports and exports CommonModule, which declares and exportsdirectives such as ngIf and ngFor.These directives are then available to any of the AppModule’scomponents templates. We also import HTTP module to register theAngular HTTP client service provider.We import RouterModule and call forRoot, passing in the configuredroutes for the root of the application.Here we configure our default route and any wildcard routes.Then we import each feature module.In this example we have only one feature module, ProductModule.The declarations array identifies the list of components that belongto this module. In this example, the root component, AppComponent,and the application’s welcome component are declared here.The bootstrap array identifies the root component, AppComponent as thebootstrap component. When Angular launches the application, it loadsthis component and displays its template.We could take the refactoring a step further and separate the routinginto its own module. We could create one Angular module for our rootapplication routes and another Angular module for our product feature routes.Let’s go back to the slides and see what that code would look like.If we wanted to refactor our root application routes into their ownmodule, this is what it might look like.We export a class, add the ngModule decorator, and import what we need.We add the router module to the imports array, passing in our rootapplication routes including our default route and our wildcard route.Notice that we call forRoot here to ensure that we register therouting service provider and we export RouterModule so we can use itfrom any module that imports this module.We import the AppRoutingModule in the AppModule here.Note that the AppRoutingModule is listed after the ProductModule inthe imports array. This is required because Angular registers theroutes based on the order of the module specified here.The ProductModule is listed first so it registers the product routesfirst, then the AppRoutingModule registers the application routesincluding the wildcard route.If the AppRoutingModule was before the ProductModule, then thewildcard route would be registered before the product routes and theproduct routes would never be accessible.So the AppRoutingModule with the wildcard route should always be lastin this list. We can do the same to refactor our product featureroutes into their own module. The key difference here is when weimport RouterModule in any feature module we pass the configuredroutes to the forChild method instead of the forRoot method.This ensures that we don’t register the routing service provider asecond time. And we import this ProductRoutingModule into theProductModule as shown here. Now let’s finish up this course modulewith some checklists and a summary.
Checklists and Summary
Your application architecture depends on many factors including thesize and scope of the application you are working on, your team sizeand experience, and your project’s goals, but here are somesuggestions based on what we covered in this course module.Every application must always have a root application module,by convention called AppModule. This is normally the module thatbootstraps the root application component, AppComponent.For smaller applications, this could be the only Angular module forthe application as was the case with our sample application prior tothis course module. As the application gets more features, considerdefining a separate Angular module for each feature set.For example, a product module, a customer module, and an invoice module.This keeps the code organized, separates the concerns, and preventsthe AppModule from getting excessively large and unwieldy.As you add feature modules you may find components, pipes, anddirectives that you want to share across feature modules.Define one or more shared modules for these shared pieces.Shared modules primarily use the exports and declarations arrays,with most of the declared pieces exported as well.If you have a set of services that you want to ensure are loaded whenthe application is loaded, consider defining a core module for those services.Be sure that the core module is imported only once, in the rootapplication module. Since a core module is for services,they primarily have providers, none of which are exported.We did not create a core module for our sample application since ourservice needs are limited, but you may find them useful for your applications.And as we discussed in the last clip, we can also refactor our routesinto their own routing modules.When creating an Angular module we build a class and decorate it withthe ngModule decorator. The ngModule metadata includes the bootstraparray for defining the list of startup components.In many cases there is only one, the root component of the application.The declarations array declares which components, directives, andpipes belong to this module.The exports array identifies the list of components, directives, andpipes that an importing module can use.The imports array lists supporting modules.These modules provide components, directives, and pipes needed by thecomponents in this module.The providers array lists the service providers.Angular registers each provider with Angular’s root applicationinjector so these services are available to be injected into any classin the application.This course module was all about Angular modules.We took a second look at the definition and purpose of an Angular module.We then focused in on the Angular module metadata and covered thetrues to keep in mind when using that metadata.We leveraged that knowledge to create a feature module for ourapplication and took it one step further, defining a shared moduleto reduce duplication in our application.Lastly, we reexamined our application root Angular module and saw howit orchestrates the application as a whole.If you are building a small application such as the sample applicationwe’ve created in this course, you may only need the one rootapplication module as shown here, but as your application grows,you’ll want to refactor into feature modules and shared modules like this.Here we organized our application into multiple modules.We have our feature module, ProductModule that encapsulates all of theproduct features. There will be more feature modules as ourapplication grows.We have our SharedModule that shares commonly used components,directives, and pipes with any module that imports it.Currently we import it into the ProductModule.As we build more feature modules, we’ll import it into them as well.And we have our AppModule that orchestrates the application.Each feature module is added to the AppModule’s imports array toextend the application with those features.Oh, it’s been quite a journey! Now let’s circle back to be beginningand spend a little more time with the Angular CLI.
Building, Testing, and Deploying with the CLI
We’ve mentioned the Angular CLI a few times in this course,but haven’t really discussed what it is or what it can do.What seemed like wizardry is instead a full-featured tool forbuilding, testing, and deploying our Angular applications.Welcome back to Angular: in this module we look closer at theAngular CLI.Let’s peek behind the curtain and learn more about this amazing tool.In this module we start with an overview and discover the purpose andbasic features of the Angular CLI. We then build an application fromscratch using the CLI and examine the many configuration and startupfiles it creates. We dig into how it serves up our application,learn more about its code generation features, take a brief look atrunning tests, and prepare the resulting application for deployment.Let’s get started.
Angular CLI Overview
The Angular CLI is a command line interface for Angular.Its primary purpose is to assist Angular developers with building anAngular application, generating Angular files, and executing, testing,and deploying Angular applications.Before you can use the CLI you need to install it.Just open a terminal window or command prompt and type npm install-g @angular/cli. This installs the CLI globally so you can use itfrom any folder. If you have not yet installed the CLI, do it now.Once you have it installed, we’ll jump into a demo and try it out.I’ve already installed the CLI. Now how can we find out what theCLI can do? One option is to use the ng help feature.Wow! That provides a lot of information.Scrolling back to the top, we can see that it is listing every commandalong with its alias or shortcut and all of its possible flags.The help is a bit easier to navigate if we request help on anindividual command. Let’s look at a simple one first.We can type ng help v for version or ng v –help.The help provides the syntax of the requested command, describes thepurpose of the command, and lists the command aliases.Here we see that we can use ng v, ng –version, or ng -v.The help also provides a list of the command flags along with their aliases.Let’s try out the version command.Type ng for the Angular CLI and the command.We’ll use the v alias and we see a nice text output including ourAngular CLI version. When you watch this course, you may have a newer version.Use the help command any time you need assistance with the CLIcommands or their flags. Now let’s build a new application fromscratch using the CLI.
Our new little application is cool and all, but it doesn’t do much.We need to add components and templates and services and modules.We do that with the generate command.We’ve already seen this command in action, but it can do so much more.If we type ng g –help, and scroll up to the top, we see text thatsays available blueprints. This lists all of the different types offiles we can generate with this command along with their available flags.We can create simple classes. We can create components with externaltemplate and style sheet files as we did with the product detailcomponent earlier in this course.We can generate our own custom directives, enum values, and routeguards as we did with our product detail guard.We can create interfaces and modules.We built both the ProductModule and SharedModule using this blueprint.We can create pipes and services all with only typing a few characters.Neat! Let’s generate a component.Type ng, g c and our component name and let’s say welcome.The output indicates that it created a style sheet file, templateHTML file, unit testing file, and TypeScript file for our component.By default, it created a welcome folder and added these files to it.Feel free to try out the generate command with any of these otherblueprints and flags.
Testing our Angular code is always important, but often neglected dueto the additional time and effort required to set up and execute the tests.The CLI makes it a bit easier by generating the testing spec andconfiguration files for us.We can run these tests using ng test and ng e2e.To run our unit tests, in the terminal window type ng test.This builds the application, launches the browser, and executes thekarma test runner. From here we can see the results of our unit tests.Angular generated four tests for us and they’ve all passed so we areall green. The test runner runs in watch mode so we can modify ourfiles and the tests will immediately rerun.I’ll close the browser and notice that it tried to bring it up again.I first need to terminate the test runner with Ctrl + C, then I’llclear the screen with CLS.We can use the e2e command to run our end-to-end tests using protractor.Let’s try that out, ng e2e.Notice that it pops up the browser, executes our application, andcloses the browser again.We can see here that it successfully executed one spec.Testing is a big topic that is beyond the scope of this course.See the Programfault library for more information about testing.Now that we have our application built and tested, we are ready to deploy.
An application is not very useful unless you can deploy it to your users.The build command helps you prepare your application for deployment.Let’s take a look.Here in the terminal window we’ll type ng build.The output is similar to the ng serve command, but now we see a distfolder here in our project.If we open the folder we see our actual bundles.We can look again at the main bundle.js file and find our code.And here is the resulting index.html file with the script tags to pullin each bundle. We can then deploy these files to a server somewhere,but wait. There’s more. When we deploy to production there are a fewmore things that we want to achieve.We want our bundles to be as small as possible.This means that we want to minify or uglify the code and performsomething called tree shaking.Tree shaking shakes up our code to drop out any dead branches,which basically means that it removes any unused pieces.We also want to pre-compile our templates.So instead of downloading the Angular compiler as part of the vendorbundles and running the compiler in the browser, we can make thebundles smaller and execute faster if we pre-compile before we deploy.This makes use of the AOT or Ahead of Time Compiler.The CLI will do all of these things for us if we simply add the –prod flag.Let’s try that out. Type ng build –prod.Now if we look at the files in the dist folder, we notice that theyhave a hash as part of the file name.This is a cache busting technique.Every time we update something in our code, it needs to be redeployedto the server. We expect the new version of the files to bedownloaded by the browser when a user accesses our application,but for performance reasons, the browser may have cached those files.By changing the file names using a hash, the browser will download thelatest version because the file names won’t match its cached versions.Notice also that there are no map files here.By default, the –prod flag does not generate map files, but there isa flag for that if you need them.Peeking in to the main bundle, all the code is on one line and look atthose variable names. It’s been minified.Glad we don’t have to debug using that code.Let’s look at some of the key flags available with the build command.Type ng build –help. We’ll scroll up a bit.There are quite a few flags here to help you tune exactly what youwant the build command to do.The –prod flag we just used is actually an alias for the–environment prod flag.The valid environment options are defined in the CLI configuration file.One of the other key flags here is the –base href.Recall that we set the base element in our index.html file to specifythe root path for our Angular routing, but when we deploy toproduction, we may not want to deploy to the root path of our server.We can use the –base href flag to set the appropriate base URL forthe deployed application. Wow, the CLI is powerful!Now let’s finish up this module with some checklists we can use as weleverage the Angular CLI.
Checklists and Summary
Here are the key CLI commands for reference.Use ng help or ng, a command name, –help to view the CLI documentation.The remaining commands here help you create, execute, build, test,and deploy your Angular application.You may find yourself using ng generate a lot so here is the list ofavailable blueprints for the generate command along with their command syntax.Refer to this checklist as you generate the code files for your application.In this module we discovered the purpose and basic features of this CLI.We built an application from scratch and examined its manyconfiguration and startup files.We dug into how it serves up our application, learned about its codegeneration features, looked at running tests, and prepared theresulting application for deployment.Now that we’ve peeked behind the curtain, you know the secrets of the CLI.There is no wizardry here.There are more commands and many more flags than what we discussed inthis module. To learn more about the Angular CLI, check out JohnPapa’s course aptly entitled, Angular CLI in the Programfault library.It covers many more of its amazing features.Only one module left.
As you have seen throughout this course, Angular provides a consistentset of patterns for building components, templates, and services,helping us to come up to speed quickly.Welcome back to Angular: the final words in this course include arecap of our journey, a few pointers to additional information, and alook at a broader description of Angular.Let’s jump right into this short module.
Recapping Our Journey
The goal of this course was to guide you down the right path, makingyour own adventures with Angular more pleasant and productive.Let’s recap our journey and review the answers to the key questionswe identified at the beginning of this course.What is a component? We discovered that a component is a view definedwith a template, logic defined with a class, and metadata defined witha decorator.Where do we put the HTML for our user interface?Either in the metadata using the template property or in a separateHTML file using the template URL file in the metadata.When should we use binding? Any time we want to display a componentclass property value in the view.When we want to control the DOM by setting a DOM element property in code.When we want to respond to user actions, and when we want to displaya component class property, and update the property when the usermakes a change.Why do we need a service? We uncovered several reasons for buildinga service. To implement functionality that is independent from anyparticular component, to share data and logic across components, andto encapsulate external interactions such as with data access.And how? How do we build an Angular application?With code that looks like this. Export a class, attach a decorator,and import what we need.Then put each component, directive, and pipe in its appropriateAngular module.Leverage the Angular CLI for creating, building, testing, anddeploying your Angular application.Along the way, each module provided a set of checklists containingsteps and tips. Feel free to revisit and reference these checklistsas you start building your own Angular applications.
This course covered the basics, but there is so much more., the Angular: First Look course provides a comparisonof Angular JS to the newer versions of Angular and presents a morefull-featured sample application.The Angular CLI course covers much more about the Angular CLI.Angular Reactive Forms covers building and validating data entry formswith Angular and details basic CRUD or create, read, update, anddelete operations using HTTP.In the Angular Routing course you’ll learn how to define more complexroutes, pass data to routes, guard your routes, pre-load data for yourviews, lazy load routes for better performance, and much more.Angular Fundamentals expands on the basics and covers moreintermediate information on every key aspect of Angular.In addition to courses, the Angular documentation is verycomprehensive and is a great reference to everything Angular.And I’ve set up a GitHub repository for this course so you can use itas a starting point or learning aide.It provides starter files if you want to try building an applicationyourself or you can review the completed course files here.
What Is Angular? (Revisited)
Congratulations! You’ve made it! Yay!You’ve completed the journey through the basics of Angular.But the road goes ever on and on. There are so many more paths forus to take and so much more to learn.Thoughts or comments about this course?.It would be great to hear about your Angular adventures.Thanks for listening and I hope you enjoyed our adventure through Angular.