Skip to content

Commit

Permalink
feat(ng2.uiSrefActive): Implement uiSrefStatus, uiSrefActive, uiSrefA…
Browse files Browse the repository at this point in the history
…ctiveEq
  • Loading branch information
christopherthielen committed Apr 3, 2016
1 parent 0eb7406 commit fcb15c5
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 62 deletions.
2 changes: 1 addition & 1 deletion src/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class UIRouterGlobals {

const clearCurrentTransition = () => { if (this.transition === $transition$) this.transition = null; };

$transition$.promise.finally(clearCurrentTransition)
$transition$.promise.then(clearCurrentTransition, clearCurrentTransition);

};

Expand Down
10 changes: 6 additions & 4 deletions src/ng2/directives.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

import {UiSref} from "../ng2/uiSref";
import {UiSrefClass} from "../ng2/uiSrefActive";
import {UiSrefActive} from "../ng2/uiSrefActive";
import {UiView} from "../ng2/uiView";
import {UiSrefStatus} from "./uiSrefStatus";

export * from "./uiView";
export * from "./uiSref";
export * from "./uiSrefStatus";
export * from "./uiSrefActive";
export * from "./uiView";

export let UIROUTER_DIRECTIVES = [UiSref, UiSrefClass, UiView];
export let UIROUTER_DIRECTIVES = [UiSref, UiView, UiSrefActive, UiSrefStatus];
3 changes: 3 additions & 0 deletions src/ng2/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {UiView} from "./uiView";
import {ng2ViewsBuilder, Ng2ViewConfig} from "./viewsBuilder";
import {Ng2ViewDeclaration} from "./interface";
import {UIRouterConfig} from "./uiRouterConfig";
import {UIRouterGlobals} from "../globals";

let uiRouterFactory = (routerConfig: UIRouterConfig) => {
let router = new UIRouter();
Expand Down Expand Up @@ -46,6 +47,8 @@ export const UIROUTER_PROVIDERS: Provider[] = [

provide(StateRegistry, { useFactory: (r: UIRouter) => { return r.stateRegistry; }, deps: [UIRouter]}),

provide(UIRouterGlobals, { useFactory: (r: UIRouter) => { return r.globals; }, deps: [UIRouter]}),

provide(UiView.INJECT.context, { useFactory: (r: StateRegistry) => { console.log(r); return r.root(); }, deps: [StateRegistry]} ),

provide(UiView.INJECT.fqn, { useValue: null })
Expand Down
2 changes: 0 additions & 2 deletions src/ng2/uiSref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export class UiSref {
@Optional() private _anchorUiSref: AnchorUiSref
) { }

set "ui-sref"(val) { this.state = val; this.update(); }
set "uiSref"(val) { this.state = val; this.update(); }
set "uiParams"(val) { this.params = val; this.update(); }
set "uiOptions"(val) { this.options = val; this.update(); }
Expand All @@ -42,7 +41,6 @@ export class UiSref {
if (this._anchorUiSref) {
this._anchorUiSref.update(this._router.stateService.href(this.state, this.params));
}
// TODO: process ui-sref-active
}

go() {
Expand Down
58 changes: 13 additions & 45 deletions src/ng2/uiSrefActive.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,20 @@
/** @module ng2 */ /** */
import {UIRouter} from "../router";
import {Directive} from "angular2/core";
import {UiSref} from "./uiSref";

@Directive({
selector: '[uiSrefClass]',
inputs: ['uiSrefClass']
})
export class UiSrefClass {
// current statuses of the bound uiSref directive
active = false;
exact = false;
entering = false;
exiting = false;
inactive = true;
import {Directive, Input, ElementRef, Host, Renderer} from "angular2/core";
import {UiSrefStatus, SrefStatus} from "./uiSrefStatus";

patterns: any;
classes: string;
sref: UiSref;
@Directive({ selector: '[uiSrefActive],[uiSrefActiveEq]' })
export class UiSrefActive {
private _classes: string[] = [];
@Input('uiSrefActive') set active(val) { this._classes = val.split("\s+")};

//constructor($transitions: TransitionService, public router: UIRouter) {
constructor(public router: UIRouter) {
this.ngOnDestroy = <any> router.transitionService.onSuccess({}, this._update.bind(this));
}

ngOnDestroy() {}

/**
* e.g.
* {
* active: 'active && !exiting',
* loading: 'entering',
* active: matches('admin.*')
* }
*/
set uiSrefClass(val) {
console.log(val); // [uiSrefClass]="{active: isActive}" logs as "{active: undefined}"
this.patterns = val;
}

public provideUiSref(sref: UiSref) {
this.sref = sref;
this._update();
}
private _classesEq: string[] = [];
@Input('uiSrefActiveEq') set activeEq(val) { this._classesEq = val.split("\s+")};

private _update() {
if (!this.sref) return;
// update classes
constructor(uiSrefStatus: UiSrefStatus, rnd: Renderer, @Host() host: ElementRef) {
uiSrefStatus.uiSrefStatus.subscribe((next: SrefStatus) => {
this._classes.forEach(cls => rnd.setElementClass(host.nativeElement, cls, next.active));
this._classesEq.forEach(cls => rnd.setElementClass(host.nativeElement, cls, next.exact));
});
}
}

101 changes: 101 additions & 0 deletions src/ng2/uiSrefStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {Directive, Output, EventEmitter} from "angular2/core";
import {StateService} from "../state/stateService";
import {UiSref} from "./uiSref";
import {UIRouter} from "../router";
import {Node} from "../path/node";
import {TransitionService} from "../transition/transitionService";
import {Transition} from "../transition/transition";
import {TargetState} from "../state/targetState";
import {TreeChanges} from "../transition/interface";
import {State} from "../state/stateObject";
import {anyTrueR, tail} from "../common/common";
import {UIRouterGlobals} from "../globals";

export interface SrefStatus {
active: boolean;
exact: boolean;
entering: boolean;
exiting: boolean;
}

/**
* Emits events when the uiSref status changes
*
* This API is subject to change.
*/
@Directive({ selector: '[uiSrefStatus],[uiSrefActive],[uiSrefActiveEq]' })
export class UiSrefStatus {
private _deregisterHook;

// current statuses of the state/params the uiSref directive is linking to
@Output("uiSrefStatus") uiSrefStatus = new EventEmitter<SrefStatus>();

status: SrefStatus = {
active: false,
exact: false,
entering: false,
exiting: false
};

constructor(transitionService: TransitionService,
private _globals: UIRouterGlobals,
private _stateService: StateService,
public sref: UiSref) {
this._deregisterHook = transitionService.onStart({}, ($transition$) => this._transition($transition$));
}

ngOnInit() {
let lastTrans = this._globals.transitionHistory.peekTail();
if (lastTrans != null) {
this._transition(lastTrans);
}
}

ngOnDestroy() {
this._deregisterHook()
}

private _setStatus(status: SrefStatus) {
this.status = status;
this.uiSrefStatus.emit(status);
}

private _transition($transition$: Transition) {
let sref = this.sref;

let status: SrefStatus = <any> {
active: false,
exact: false,
entering: false,
exiting: false
};

let srefTarget: TargetState = this._stateService.target(sref.state, sref.params, sref.options);
if (!srefTarget.exists()) {
return this._setStatus(status);
}

let tc: TreeChanges = $transition$.treeChanges();
let state: State = srefTarget.$state();
const isTarget = (node: Node) => node.state === state;

status.active = tc.from.map(isTarget).reduce(anyTrueR, false);
status.exact = tail(tc.from.map(isTarget)) === true;
status.entering = tc.entering.map(isTarget).reduce(anyTrueR, false);
status.exiting = tc.exiting.map(isTarget).reduce(anyTrueR, false);

if ($transition$.isActive()) {
this._setStatus(status);
}

let update = (currentPath: Node[]) => () => {
if (!$transition$.isActive()) return; // superseded
status.active = currentPath.map(isTarget).reduce(anyTrueR, false);
status.exact = tail(currentPath.map(isTarget)) === true;
status.entering = status.exiting = false;
this._setStatus(status);
};

$transition$.promise.then(update(tc.to), update(tc.from));
}
}
21 changes: 11 additions & 10 deletions src/ng2/uiView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,17 @@ const getProviders = (injector) => {
color: grey;
}`
],
template: `
<div style="padding: 1em; border: 1px solid lightgrey;">
<div #content style="color: lightgrey; font-size: smaller;">
<div>ui-view #{{uiViewData.id}} created by '{{ parentContext.name || "(root)" }}' state</div>
<div>name: (absolute) '{{uiViewData.fqn}}' (contextual) '{{uiViewData.name}}@{{parentContext.name}}' </div>
<div>currently filled by: '{{(uiViewData.config && uiViewData.config.context) || 'empty...'}}'</div>
</div>
</div>`
template: `<div #content></div>`,
// debugtemplate: `
// <div style="padding: 1em; border: 1px solid lightgrey;">
//
// <div #content style="color: lightgrey; font-size: smaller;">
// <div>ui-view #{{uiViewData.id}} created by '{{ parentContext.name || "(root)" }}' state</div>
// <div>name: (absolute) '{{uiViewData.fqn}}' (contextual) '{{uiViewData.name}}@{{parentContext.name}}' </div>
// <div>currently filled by: '{{(uiViewData.config && uiViewData.config.context) || 'empty...'}}'</div>
// </div>
//
// </div>`
})
export class UiView {
@Input() name: string;
Expand Down

0 comments on commit fcb15c5

Please sign in to comment.