Angular2 Notes V

  • Interval and Clock Ticker

Use IntervalObservable in rxjs to implement interval in angular 2. Create(period) is a static method, which creates an Observable that emits sequential numbers every specified interval of time.

import { IntervalObservable } from 'rxjs/observable/IntervalObservable';
@Component({
selector: 'demo',
templateUrl: '<div>{{time | date:'HH:mm:ss'}}</div>'
})
export class Demo implements OnInit{
time:number = Date.now();
ngOnInit() {
IntervalObservable.create(1000).subscribe(() => this.time = Date.now());
}
}
  • ngOnChanges Not Detect Changes in Object

During change detection, when Angular checks components’ input properties for change, it uses (essentially) === for dirty checking. For arrays, this means the array references (only) are dirty checked. Since the rawLapsData array reference isn’t changing, ngOnChanges() will not be fired.

Two possible solutions:

  1. Implement ngDoCheck() and perform your own change detection logic to determine if the array contents have changed.
  2. Assign a new array to rawLapsData whenever you make any changes to the array contents. Then ngOnChanges() will be called because the array (reference) will appear as a change.
  • Number Pipe Parameters

For example,

{{ tmpNumber | number : '1.2-2' }}

The parameter has this syntax:

{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}

So the example of ‘1.2-2’ means:

  1. A minimum of 1 digit will be shown before decimal point.
  2. Show at least 2 digits after decimal point.
  3. No more than 2 digits.
  • Matrix URL

Matrix parameters are tied to a path segment, while query parameters are tied to the URL. They have different semantics.

Maybe it’s hard to tell because you always see it at the end of the URL, but this is also matrix paramters
localhost:3000/heroes;id=15;foo=foo/bar/baz

The parameters are tied to heroes. When you access the route.url, you will see this

this.route.url.subscribe((url: UrlSegment[]) => {
let heroes = url[0];
let heroesMatrix = heroes.parameters();
// heroes should contain id=5, foo=foo
let bar = url[1].path;
let baz = url[2].path;
})

Is the matrix url notation the “default” to creating urls with parameters or is better to use the “old” notation with ?

No, both could be used, and how to use (create) them is completely different

matrix parameters are tied to each path, by passing an object after the path in the array

router.navigate(['/foo', { id:1 }, 'bar', {baz: 2 } ])

Here you will get /foo;id=1/bar;baz=2.

Query parameters are created by passing the NavigationExtras as the second argument to navigate

router.navigate(['/foo'], { queryParams: { bar: 1, baz: 2 }});

Here you get /foo?bar=1&baz=2

See also:

When to use query parameters versus matrix parameters?

URL matrix parameters vs. request parameters

  • canActivate Return Observable

Note:

  1. CanActive is an interface, that indicates a class can be implement to be a guard deciding if a route can be activated.
  2. Implement canActivate() method. It can return with 3 types.
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean>|Promise<boolean>|boolean
  3. We can get previous path through RouterStateSnapshot.
  4. Passing parameters via router.navigate(), and the passed params are matrix URL pattern rather than query params.
    Have to pass the matrix URL parameters to the redirected error page, so that the error page knows what is the link that user wants to access causing an error.
  5. Hope to replace window.location.hrefin the future, it is not written in angular way.
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot): Observable<boolean> {
this.path = state.url;
return this.roleResourceService.checkStaffRoleResource(this.path)
.map(isActivate => {
if(!isActivate) {
this.onCanActivate(isActivate);
}
return isActivate;
});
}

onCanActivate(canActivate:boolean) {
if (!canActivate) {
this.router.navigate(['', 'error-role', {path: this.path}]);
this.roleResourceService.clearCache();
}
}
  • Detect Route Changes

import { Router, NavigationStart, NavigationEnd, NavigationError, NavigationCancel, RoutesRecognized } from '@angular/router';

constructor(router:Router) {
router.events.forEach((event) => {
if(event instanceof NavigationStart) {
}
// NavigationEnd
// NavigationCancel
// NavigationError
// RoutesRecognized
});
}

You can also filter by the given event:

import 'rxjs/add/operator/filter';

constructor(router:Router) {
router.events
.filter(event => event instanceof NavigationStart)
.subscribe((event:NavigationStart) => {
// You only receive NavigationStart events
});
}

Using pairwise operator to get the previous and current event also is an nice idea.

import 'rxjs/add/operator/pairwise';
import {Router} from '@angular/router;

export class AppComponent {
constructor(private router: Router) {
this.router.events.pairwise().subscribe((e) => {
console.log(e);
}
});
}

Ref:

  1. Rxjs IntervalObservable
  2. When to use query parameters versus matrix parameters?
  3. URL matrix parameters vs. request parameters
  4. Using pairwise operator