Unit 2 Notes from Yakov Fain online Angular training, spring 2016

Component router:

  • Allows the user to navigate from one view to another in a SPA.
  • There are two location strategies:
    • HashLocationStrategy – a hash sign is added to the URL and the fragment after the hash sign identifies the route on the client. (Works in all browsers.)
    • PathLocationStrategy – Supported only in browsers that support HTML5.
  • The router is a service implemented by a collection of Dependency Injection providers, most of which are identified in the ROUTER_PROVIDERS array.
  • In the example below,we’re booting Angular 2 with RootComponent as our app’s root component and registering providers in the providers array in the second parameter of the bootstrap function. Providing the router providers at the root makes the Component Router available everywhere in our application.
  • The default location strategy is PathLocationStrategy. You can use the class HashLocationStrategy : bootstrap(RootComponent, [ROUTER_PROVIDERS,  provide(LocationStrategy, {useClass: HashLocationStrategy})]

 

Routing Building Blocks

  • RouterOutlet (<router-outlet>) – where the router should render the component
  • @RouteConfig – Thus decorator maps URLs to components to be rendered inside the <router-outlet>. Note: The preferred way to simultaneously create a router and add its routes is with a @RouteConfig decorator applied to the router’s host component.
  • RouterLink The RouterLink directive lets you link to specific parts of your app. ([routerLink]) – a link to a named route using <a [routerLink] …>
  • RouteParams – a map of key-value pairs to pass parameters to the route
  • RouteData – a map of key-value pairs used to pass additional data from @RouteConfig to a route

Note: An ellipse in a RouteConfig path indicates the child has its own routes.

@RouteConfig([
{path: ‘/’, component: HomeComponent, as: ‘Home’},
{path: ‘/product/:id/‘, component: ProductDetailComponent, as: ‘ProductDetail’ } 
])


 

Lazy loading of routes

In large apps you can improve performance by limiting the amount of initially downloaded code. This can be accomplished by specifying a *loader in the @RouteConfig decorator. When this approach is employed, the underlying component is not loaded until a link to it is clicked on. Here’s an example from unit 2’s Walkthrough 4:

    {path: ‘/luxury’,
            loader: ()=> System.import(‘app/components/luxury’)
                               .then(libModule => libModule.LuxuryComponent), as: ‘Luxury’
 }

The loader for the LuxuryComponent will return a promise.

*Per Theirry Templier’s answer to my 04.10.2016 stackoverflow.com question, Angular2 creates an AsyncRoute when the loader attribute is present in the route definition. He shows the Angular 2 function that does so and notes that the code above gets transpiled into the the same javascript as newing up an AsyncRoute would.

{path: '/luxury',
    loader: ()=> System.import('app/components/luxury')
        .then(libModule => libModule.LuxuryComponent), as: 'Luxury' }

You can take a look at Chrome Dev Tools New work tab before and after clicking on the link to the component to verify this.


 

Child Routes

A child component can have its own routes configured. One of the child’s routes needs to be defined as the default route or Angular 2 will throw an error.

Yakov’s slide 14 in the unit 2 handout shows one way to do this. However, it appears that there is a simpler approach in the Angular 2 Guide’s Router section here. It involves the use of the useAsDefault property on a route definition. Here’s an example from the guide:

{ // Crisis Center child route path: '/crisis-center/...', name: 'CrisisCenter', component: CrisisCenterComponent, useAsDefault: true },

NOTE: As of late April, 2016, I am not able to get useAsDefault to work…

Remember, an ellipse in a RouteConfig path indicates the child has its own routes.


Type Definitions

*.d.ts files declare types for JavaScript libraries and frameworks.

Modules can be declared with the keyword declare, without linking to the actual JS code, These types are called ‘ambient’.

tsc searches for all *.d.ts files in subdirs starting from the root dir specified as rootDir in tsconfig.json.

Angular 2 defines all the type definitions it needs.

If your IDE shows some type in red or with a squiggly red lines under it, that indicates that it can’t find the definition for that type. Solve this by installing the required d.ts files.

Newer type definition manager is ‘typings’. typings can install definitions from various repositories (unlike its predecessor, tsd,which can only install types from definitleytyped.org. See example below:

typings install jquery --ambient --save

Note that without ‘–ambient’ the typings type definition manager will try to find the d.ts file in its own registry (which is at https://github.com/typings/registry.)


How tsc finds modules using the (npm) node module-resolution strategy

Set the module property value to “commonjs” in the tsconfig.json file’s compilerOptions. This will set up tsc to follow the node strategy, which is outlined here:

  • The transpiler will look for ambient declarations (in the node_modules directory) such as
    • import {Component} from 'angular2/core'
  • Then it will check if the path is relative, such as
    • import {Product} from './product.service'
    • tsc will look in the project’s root folder and below for the following in the following order to determine the module and its members’ signatures:
      • a product.service.ts file
      • then, if not found, product.service.d.ts
      • If neither are found, it will look in the node_modules directory

Input and Output properties -Torgeir Helgevold has a nice February, 2016 summary here.

  • Properties marked Input() are for getting data into a child component from the parent. (See slide 26 and/or 1H 25M mark of the video for example.)
    • Note that a parent component will need to include its child(ren) in its @Component decorator’s directives property. Like this:
      directives: [childNameblahblahblahComponent]
    • The parent component passes data to a child using bindings to input properties.
    • The purpose of @Input is to configure data bound input properties with support for change tracking.
  • Properties marked Output() are for sending events from a component.
    • A parent needs the following to listen for an event in a child component:
      • An event-handler function such as:
        priceQuoteHandler (event:IPriceQuote) {
            this.stockSymbil = event.stockSymbol;
            this.price = event.lastPrice;
        }
      • A template or template file that contains a child component’s selector with a property that reference’s the event-handler function in the parent, such as:
        template: `
            <price-quoter (last-price)=“priceQuoteHandler($event)"></price-quoter><br>
            AppComponent received: {{stockSymbol}} {{price | currency:’USD’:true:'1.2-2'}}
        `
  • The child uses instances of the EventEmitter class to send events via Output properties like this:
    @Output ('last=price') lastPrice: EventEmitter <IPriceQuote> = new EventEmitter();
  • The constructor or other function emits the event via the EventEmitter instance like this:
    this.lastPrice.emit(priceQuote);

The Mediator design pattern

See slide 36 & unit2\inter_comp_communications\app\mediator for example

  • The mediator acts as a ‘man in the middle’ and allows for loose coupling of components.
  • A parent component can mediate siblings’ communication therefore the siblings do not need to know about one another. For example, a button on a child component can be clicked to emit data to the parent which can then bind it to a property on another child component.
  • An injected service can mediate communication between any components (an IoC design pattern)

Shadow DOM

  • Every web page is represented by a tree of DOM objects.
  • Shadow DOM allows for encapsulation of a subtree of HTML elements to create a boundary between components.
    • Such a subtree is rendered as part of the HTML document, but its elements are not attached to the main DOM tree.
  • With Shadow DOM the CSS styels of the custom component won’t be merged with the main DOM CSS – nice!
  • encapsulation property of @Component:
    • ViewEncapsulation.Emulated – Emulate encapsulation of the Shadow DOM (default)
    • ViewEncapsulation.Native – Use Shadow DOM natively supported by the browser
    • ViewEncapsulation.None – Don’t use the Shadow DOM encapsulation.

Also, see my additional Shadow DOM links


Dynamically passing HTML to a Child

  • A component can have only one template, but a parent can pass an HTML fragment to a child’s template during runtime. (See slide 40)
  • Add the <ng-content tag to the child’s template to do so.
  • This is called projection (aka ‘transclusion’ in Angular 1)
Advertisements

One thought on “Unit 2 Notes from Yakov Fain online Angular training, spring 2016

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s