feat(router): add RouterLink
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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>,
|
||||
|
||||
Reference in New Issue
Block a user