Skip to content

Commit

Permalink
fix(angular): stack based navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Mar 27, 2018
1 parent 46bbd0f commit 726938f
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 117 deletions.
1 change: 1 addition & 0 deletions angular/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { ToastController } from './providers/toast-controller';

// navigation
export { GoBack } from './navigation/go-back';
export { IonBackButton } from './navigation/ion-back-button';
export { NavController } from './navigation/ion-nav-controller';
export { Nav } from './navigation/ion-nav';
export { IonRouterOutlet } from './navigation/ion-router-outlet';
Expand Down
3 changes: 3 additions & 0 deletions angular/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { TextValueAccessor } from './control-value-accessors/text-value-accessor

// navigation
import { GoBack } from './navigation/go-back';
import { IonBackButton } from './navigation/ion-back-button';
import { NavController } from './navigation/ion-nav-controller';
import { Nav } from './navigation/ion-nav';
import { Tab } from './navigation/ion-tab';
Expand Down Expand Up @@ -222,6 +223,7 @@ import {
Tab,
Tabs,
GoBack,
IonBackButton,

// router
IonRouterOutlet,
Expand Down Expand Up @@ -331,6 +333,7 @@ import {
Nav,
IonRouterOutlet,
GoBack,
IonBackButton,
Tab,
Tabs,
NumericValueAccessor,
Expand Down
27 changes: 27 additions & 0 deletions angular/src/navigation/ion-back-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Directive } from '@angular/core';

@Directive({
selector: 'ion-back-button'
})
export class IonBackButton {

// constructor(
// private navCtrl: NavController,
// private router
// @Optional() private routerOutlet: IonRouterOutlet,
// ) {
// routerOutlet.
// }



// @HostListener('click')
// onClick() {
// if(routerOutlet.canGoBack())
// this.navCtrl.setGoback();
// if (!this.routerLink) {
// window.history.back();
// }
// }

}
26 changes: 13 additions & 13 deletions angular/src/navigation/ion-nav-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ import { Injectable } from '@angular/core';
@Injectable()
export class NavController {

private direction = 0;
private stack: string[] = [];
private direction = 1;
// private stack: string[] = [];

setGoback() {
this.direction = -1;
}

consumeDirection() {
if (this.direction === 0) {
const index = this.stack.indexOf(document.location.href);
if (index === -1) {
this.stack.push(document.location.href);
this.direction = 1;
} else {
this.stack = this.stack.slice(0, index + 1);
this.direction = -1;
}
}
// if (this.direction === 0) {
// const index = this.stack.indexOf(document.location.href);
// if (index === -1) {
// this.stack.push(document.location.href);
// this.direction = 1;
// } else {
// this.stack = this.stack.slice(0, index + 1);
// this.direction = -1;
// }
// }
const direction = this.direction;
this.direction = 0;
this.direction = 1;
return direction;
}
}
85 changes: 42 additions & 43 deletions angular/src/navigation/ion-router-outlet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, OnDestroy, OnInit, Output, ViewContainerRef } from '@angular/core';
import { ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET } from '@angular/router';
import { NavController } from './ion-nav-controller';
import { NavDirection } from '@ionic/core/dist/types/components/nav/nav-util';
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, OnDestroy, OnInit, Optional, Output, ViewContainerRef } from '@angular/core';
import { ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET, Router } from '@angular/router';
import { StackController } from './router-controller';

@Directive({
selector: 'ion-router-outlet',
Expand All @@ -10,10 +9,10 @@ import { NavDirection } from '@ionic/core/dist/types/components/nav/nav-util';
export class IonRouterOutlet implements OnDestroy, OnInit {

private activated: ComponentRef<any>|null = null;
private deactivated: ComponentRef<any>|null = null;

private _activatedRoute: ActivatedRoute|null = null;
private name: string;
private stackCtrl: StackController;

@Output('activate') activateEvents = new EventEmitter<any>();
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
Expand All @@ -22,13 +21,16 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
private parentContexts: ChildrenOutletContexts,
private location: ViewContainerRef,
private resolver: ComponentFactoryResolver,
private elementRef: ElementRef,
elementRef: ElementRef,
@Attribute('name') name: string,
@Optional() @Attribute('stack') stack: any,
private changeDetector: ChangeDetectorRef,
private navCtrl: NavController
// private navCtrl: NavController,
router: Router
) {
this.name = name || PRIMARY_OUTLET;
parentContexts.onChildOutletCreated(this.name, this as any);
this.stackCtrl = new StackController(stack != null, elementRef.nativeElement, router);
}

ngOnDestroy(): void {
Expand All @@ -55,12 +57,16 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
get isActivated(): boolean { return !!this.activated; }

get component(): Object {
if (!this.activated) throw new Error('Outlet is not activated');
if (!this.activated) {
throw new Error('Outlet is not activated');
}
return this.activated.instance;
}

get activatedRoute(): ActivatedRoute {
if (!this.activated) throw new Error('Outlet is not activated');
if (!this.activated) {
throw new Error('Outlet is not activated');
}
return this._activatedRoute as ActivatedRoute;
}

Expand All @@ -75,7 +81,9 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
* Called when the `RouteReuseStrategy` instructs to detach the subtree
*/
detach(): ComponentRef<any> {
if (!this.activated) throw new Error('Outlet is not activated');
if (!this.activated) {
throw new Error('Outlet is not activated');
}
this.location.detach();
const cmp = this.activated;
this.activated = null;
Expand All @@ -95,7 +103,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
deactivate(): void {
if (this.activated) {
const c = this.component;
this.deactivated = this.activated;
this.activated = null;
this._activatedRoute = null;
this.deactivateEvents.emit(c);
Expand All @@ -107,46 +114,38 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
throw new Error('Cannot activate an already activated outlet');
}
this._activatedRoute = activatedRoute;
const snapshot = (activatedRoute as any)._futureSnapshot;

const component = <any>snapshot.routeConfig !.component;
resolver = resolver || this.resolver;
let enteringView = this.stackCtrl.getExistingView(activatedRoute);
if (enteringView) {
this.activated = enteringView.ref;
} else {
const snapshot = (activatedRoute as any)._futureSnapshot;

const factory = resolver.resolveComponentFactory(component);
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
const component = <any>snapshot.routeConfig !.component;
resolver = resolver || this.resolver;

const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
this.activated = this.location.createComponent(factory, this.location.length, injector);
const factory = resolver.resolveComponentFactory(component);
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;

// Calling `markForCheck` to make sure we will run the change detection when the
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
this.changeDetector.markForCheck();
await this.transition();
this.activateEvents.emit(this.activated.instance);
}
const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
this.activated = this.location.createComponent(factory, this.location.length, injector);

async transition() {
const enteringRef = this.activated;
const enteringEl = (enteringRef && enteringRef.location && enteringRef.location.nativeElement) as HTMLElement;
if (enteringEl) {
enteringEl.classList.add('ion-page', 'hide-page');

const navEl = this.elementRef.nativeElement as HTMLIonRouterOutletElement;
navEl.appendChild(enteringEl);
// Calling `markForCheck` to make sure we will run the change detection when the
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
this.changeDetector.markForCheck();
enteringView = this.stackCtrl.createView(this.activated, activatedRoute);
}

const direction = this.navCtrl.consumeDirection();
await this.stackCtrl.setActive(enteringView, undefined);
this.activateEvents.emit(this.activated.instance);
}

await navEl.componentOnReady();
await navEl.commit(enteringEl, {
duration: direction === 0 ? 0 : undefined,
direction: direction === -1 ? NavDirection.back : NavDirection.forward
});
canGoBack(deep = 1) {
return this.stackCtrl.canGoBack(deep);
}

if (this.deactivated) {
this.deactivated.destroy();
this.deactivated = null;
}
}
pop(deep = 1) {
return this.stackCtrl.pop(deep);
}
}

Expand Down
Loading

0 comments on commit 726938f

Please sign in to comment.