feat(router): add RouterLink

This commit is contained in:
vsavkin
2016-04-27 15:37:20 -07:00
committed by Victor Savkin
parent fa5bfe4b64
commit de56dd5f30
4 changed files with 212 additions and 89 deletions
@@ -0,0 +1,59 @@
import {
ResolvedReflectiveProvider,
Directive,
DynamicComponentLoader,
ViewContainerRef,
Attribute,
ComponentRef,
ComponentFactory,
ReflectiveInjector,
OnInit,
HostListener,
HostBinding,
Input,
OnDestroy
} from 'angular2/core';
import {RouterOutletMap, Router} from '../router';
import {RouteSegment, UrlSegment, Tree} from '../segments';
import {link} from '../link';
import {isString} from 'angular2/src/facade/lang';
import {ObservableWrapper} from 'angular2/src/facade/async';
@Directive({selector: '[routerLink]'})
export class RouterLink implements OnDestroy {
@Input() target: string;
private _changes: any[] = [];
private _targetUrl: Tree<UrlSegment>;
private _subscription: any;
@HostBinding() private href: string;
constructor(private _router: Router, private _segment: RouteSegment) {
this._subscription = ObservableWrapper.subscribe(_router.changes, (_) => {
this._targetUrl = _router.urlTree;
this._updateTargetUrlAndHref();
});
}
ngOnDestroy() { ObservableWrapper.dispose(this._subscription); }
@Input()
set routerLink(data: any[]) {
this._changes = data;
this._updateTargetUrlAndHref();
}
@HostListener("click")
onClick(): boolean {
if (!isString(this.target) || this.target == '_self') {
this._router.navigate(this._targetUrl);
return false;
}
return true;
}
private _updateTargetUrlAndHref(): void {
this._targetUrl = link(this._segment, this._router.urlTree, this._changes);
this.href = this._router.serializeUrl(this._targetUrl);
}
}
+31 -12
View File
@@ -1,9 +1,10 @@
import {provide, ReflectiveInjector, ComponentResolver} from 'angular2/core';
import {RouterOutlet} from './directives/router_outlet';
import {Type, isBlank, isPresent} from 'angular2/src/facade/lang';
import {EventEmitter, Observable} from 'angular2/src/facade/async';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {BaseException} from 'angular2/src/facade/exceptions';
import {RouterUrlParser} from './router_url_parser';
import {RouterUrlSerializer} from './router_url_serializer';
import {recognize} from './recognize';
import {
equalSegments,
@@ -11,7 +12,9 @@ import {
RouteSegment,
Tree,
rootNode,
TreeNode
TreeNode,
UrlSegment,
serializeRouteSegmentTree
} from './segments';
import {hasLifecycleHook} from './lifecycle_reflector';
import {DEFAULT_OUTLET_NAME} from './constants';
@@ -23,23 +26,39 @@ export class RouterOutletMap {
}
export class Router {
private prevTree: Tree<RouteSegment>;
constructor(private _componentType: Type, private _componentResolver: ComponentResolver,
private _urlParser: RouterUrlParser, private _routerOutletMap: RouterOutletMap) {}
private _prevTree: Tree<RouteSegment>;
private _urlTree: Tree<UrlSegment>;
navigateByUrl(url: string): Promise<void> {
let urlSegmentTree = this._urlParser.parse(url);
return recognize(this._componentResolver, this._componentType, urlSegmentTree)
private _changes: EventEmitter<void> = new EventEmitter<void>();
constructor(private _componentType: Type, private _componentResolver: ComponentResolver,
private _urlSerializer: RouterUrlSerializer,
private _routerOutletMap: RouterOutletMap) {}
get urlTree(): Tree<UrlSegment> { return this._urlTree; }
navigate(url: Tree<UrlSegment>): Promise<void> {
this._urlTree = url;
return recognize(this._componentResolver, this._componentType, url)
.then(currTree => {
let prevRoot = isPresent(this.prevTree) ? rootNode(this.prevTree) : null;
new _SegmentLoader(currTree, this.prevTree)
let prevRoot = isPresent(this._prevTree) ? rootNode(this._prevTree) : null;
new _LoadSegments(currTree, this._prevTree)
.loadSegments(rootNode(currTree), prevRoot, this._routerOutletMap);
this.prevTree = currTree;
this._prevTree = currTree;
this._changes.emit(null);
});
}
serializeUrl(url: Tree<UrlSegment>): string { return this._urlSerializer.serialize(url); }
navigateByUrl(url: string): Promise<void> {
return this.navigate(this._urlSerializer.parse(url));
}
get changes(): Observable<void> { return this._changes; }
}
class _SegmentLoader {
class _LoadSegments {
constructor(private currTree: Tree<RouteSegment>, private prevTree: Tree<RouteSegment>) {}
loadSegments(currNode: TreeNode<RouteSegment>, prevNode: TreeNode<RouteSegment>,