refactor(overlays): inject overlay providers

BREAKING CHANGES:

- Overlay components, such as Alert or Modals, should now be created
using its injected provider.
- Overlays now have the `present()` method on the overlay’s instance,
rather than using `nav.present(overlayInstance)`.
- All overlays now present on top of all app content, to include menus.
- Below is an example of the change to `Alert`, but the pattern is the
same for all overlays: ActionSheet, Loading, Modal, Picker, Popover,
Toast

WAS:

```
import { NavController, Alert } from ‘ionic-angular’;

constructor(private nav: NavController) {
}

doAlert() {
  let alert = Alert.create({
    title: 'Alert',
  });
  this.nav.present(alert);
}
```

NOW:

```
import { AlertController } from ‘ionic-angular’;

constructor(private alertCtrl: AlertController) {
}

doAlert() {
  let alert = this.alertCtrl.create({
    title: 'Alert'
  });
  alert.present();
}
```
This commit is contained in:
Adam Bradley
2016-06-28 15:18:09 -05:00
parent 2fe42ed63e
commit 215c6d846c
39 changed files with 3578 additions and 3303 deletions

View File

@ -8,11 +8,12 @@ import { isBlank, pascalCaseToDashCase } from '../../util/util';
import { Keyboard } from '../../util/keyboard';
import { MenuController } from '../menu/menu-controller';
import { NavParams } from './nav-params';
import { NavPortal } from './nav-portal';
import { NavOptions } from './nav-options';
import { SwipeBackGesture } from './swipe-back';
import { Transition } from '../../transitions/transition';
import { ViewController } from './view-controller';
/**
* @name NavController
* @description
@ -52,8 +53,8 @@ import { ViewController } from './view-controller';
*
* ```ts
* class MyComponent {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* }
* ```
@ -162,7 +163,6 @@ export class NavController extends Ion {
private _trans: Transition;
private _sbGesture: SwipeBackGesture;
private _sbThreshold: number;
private _portal: NavPortal;
private _viewport: ViewContainerRef;
private _children: any[] = [];
@ -240,20 +240,6 @@ export class NavController extends Ion {
this.viewDidUnload = new EventEmitter();
}
/**
* @private
*/
getPortal(): NavController {
return this._portal;
}
/**
* @private
*/
setPortal(val: NavPortal) {
this._portal = val;
}
/**
* @private
*/
@ -283,8 +269,8 @@ export class NavController extends Ion {
* import {Info } from '../info/info'
*
* export class Home {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* setPages() {
* this.nav.setPages([ {page: List}, {page: Detail}, {page:Info} ]);
@ -306,8 +292,8 @@ export class NavController extends Ion {
* import {Detail } from '../detail/detail'
*
* export class Home {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* setPages() {
* this.nav.setPages([ {page: List}, {page: Detail} ], {
@ -328,8 +314,8 @@ export class NavController extends Ion {
* import {Detail } from '../detail/detail';
*
* export class Home {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* setPages() {
* this.nav.setPages([{
@ -427,8 +413,8 @@ export class NavController extends Ion {
*
* ```ts
* class MyClass{
* constructor(nav: NavController){
* this.nav = nav;
* constructor(private nav: NavController){
*
* }
*
* pushPage(user){
@ -456,68 +442,14 @@ export class NavController extends Ion {
}
/**
* Present is how an app display overlays on top of the content, from within the
* root level `NavController`. The `present` method is used by overlays, such
* as `ActionSheet`, `Alert`, and `Modal`. The main difference between `push`
* and `present` is that `present` takes a `ViewController` instance, whereas
* `push` takes a component class which hasn't been instantiated yet.
* Additionally, `present` will place the overlay in the root NavController's
* stack.
*
* ```ts
* class MyClass{
* constructor(nav: NavController) {
* this.nav = nav;
* }
*
* presentModal() {
* let modal = Modal.create(ProfilePage);
* this.nav.present(modal);
* }
* }
* ```
*
* @param {ViewController} enteringView The component you want to push on the navigation stack.
* @param {object} [opts={}] Nav options to go with this transition.
* @returns {Promise} Returns a promise which is resolved when the transition has completed.
* @private
* DEPRECATED: Please use inject the overlays controller and use the present method on the instance instead.
*/
present(enteringView: ViewController, opts?: NavOptions): Promise<any> {
let rootNav = this.rootNav;
if (rootNav['_tabs']) {
// TODO: must have until this goes in
// https://github.com/angular/angular/issues/5481
console.error('A parent <ion-nav> is required for ActionSheet/Alert/Modal/Loading');
return;
}
if (isBlank(opts)) {
opts = {};
}
if (enteringView.usePortal && rootNav._portal) {
return rootNav._portal.present(enteringView, opts);
}
enteringView.setNav(rootNav);
opts.keyboardClose = false;
opts.direction = 'forward';
if (!opts.animation) {
opts.animation = enteringView.getTransitionName('forward');
}
enteringView.setLeavingOpts({
keyboardClose: false,
direction: 'back',
animation: enteringView.getTransitionName('back'),
ev: opts.ev
});
// present() always uses the root nav
// start the transition
return rootNav._insertViews(-1, [enteringView], opts);
private present(enteringView: ViewController, opts?: NavOptions): Promise<any> {
// deprecated warning: added beta.11 2016-06-27
console.warn('nav.present() has been deprecated.\n' +
'Please use inject the overlays controller and use the present method on the instance instead.');
return Promise.resolve();
}
/**
@ -526,8 +458,8 @@ export class NavController extends Ion {
*
* ```ts
* export class Detail {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* insertPage(){
* this.nav.insert(1, Info);
@ -552,8 +484,8 @@ export class NavController extends Ion {
*
* ```ts
* export class Detail {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* insertPages(){
* let pages = [
@ -577,10 +509,13 @@ export class NavController extends Ion {
*/
insertPages(insertIndex: number, insertPages: Array<{page: any, params?: any}>, opts?: NavOptions): Promise<any> {
let views = insertPages.map(p => new ViewController(p.page, p.params));
return this._insertViews(insertIndex, views, opts);
return this.insertViews(insertIndex, views, opts);
}
private _insertViews(insertIndex: number, insertViews: ViewController[], opts?: NavOptions): Promise<any> {
/**
* @private
*/
insertViews(insertIndex: number, insertViews: ViewController[], opts?: NavOptions): Promise<any> {
if (!insertViews || !insertViews.length) {
return Promise.reject('invalid pages');
}
@ -764,8 +699,8 @@ export class NavController extends Ion {
*
* ```ts
* export class Detail {
* constructor(nav: NavController) {
* this.nav = nav;
* constructor(private nav: NavController) {
*
* }
* removePage(){
* this.nav.remove(1);
@ -832,10 +767,12 @@ export class NavController extends Ion {
// only we're looking for an actual NavController w/ stack of views
leavingView.fireWillLeave();
this.viewWillLeave.emit(leavingView);
this._app.viewWillLeave.emit(leavingView);
return parentNav.pop(opts).then((rtnVal: boolean) => {
leavingView.fireDidLeave();
this.viewDidLeave.emit(leavingView);
this._app.viewDidLeave.emit(leavingView);
return rtnVal;
});
}
@ -934,6 +871,7 @@ export class NavController extends Ion {
view.state = STATE_INIT_LEAVE;
view.fireWillUnload();
this.viewWillUnload.emit(view);
this._app.viewWillUnload.emit(view);
// from the index of the leaving view, go backwards and
// find the first view that is inactive so it can be the entering
@ -967,9 +905,7 @@ export class NavController extends Ion {
// apart of any transitions that will eventually happen
this._views.filter(v => v.state === STATE_REMOVE).forEach(view => {
view.fireWillLeave();
this.viewWillLeave.emit(view);
view.fireDidLeave();
this.viewDidLeave.emit(view);
this._views.splice(this.indexOf(view), 1);
view.destroy();
});
@ -1004,7 +940,6 @@ export class NavController extends Ion {
// if no entering view then create a bogus one
enteringView = new ViewController();
enteringView.fireLoaded();
this.viewDidLoad.emit(enteringView);
}
/* Async steps to complete a transition
@ -1062,6 +997,8 @@ export class NavController extends Ion {
this.loadPage(enteringView, this._viewport, opts, () => {
enteringView.fireLoaded();
this.viewDidLoad.emit(enteringView);
this._app.viewDidLoad.emit(enteringView);
this._postRender(transId, enteringView, leavingView, isAlreadyTransitioning, opts, done);
});
}
@ -1122,6 +1059,7 @@ export class NavController extends Ion {
// view hasn't explicitly set not to
enteringView.fireWillEnter();
this.viewWillEnter.emit(enteringView);
this._app.viewWillEnter.emit(enteringView);
}
if (enteringView.fireOtherLifecycles) {
@ -1129,6 +1067,7 @@ export class NavController extends Ion {
// view hasn't explicitly set not to
leavingView.fireWillLeave();
this.viewWillLeave.emit(leavingView);
this._app.viewWillLeave.emit(leavingView);
}
} else {
@ -1243,6 +1182,7 @@ export class NavController extends Ion {
// view hasn't explicitly set not to
enteringView.fireDidEnter();
this.viewDidEnter.emit(enteringView);
this._app.viewDidEnter.emit(enteringView);
}
if (enteringView.fireOtherLifecycles) {
@ -1250,6 +1190,7 @@ export class NavController extends Ion {
// view hasn't explicitly set not to
leavingView.fireDidLeave();
this.viewDidLeave.emit(leavingView);
this._app.viewDidLeave.emit(leavingView);
}
}
@ -1357,14 +1298,6 @@ export class NavController extends Ion {
// see if we should add the swipe back gesture listeners or not
this._sbCheck();
if (this._portal) {
this._portal._views.forEach(view => {
if (view.data && view.data.dismissOnPageChange) {
view.dismiss();
}
});
}
} else {
// darn, so this wasn't the most recent transition
// so while this one did end, there's another more recent one
@ -1408,6 +1341,8 @@ export class NavController extends Ion {
destroys.forEach(view => {
this._views.splice(this.indexOf(view), 1);
view.destroy();
this.viewDidUnload.emit(view);
this._app.viewDidUnload.emit(view);
});
// if any z-index goes under 0, then reset them all
@ -1771,6 +1706,17 @@ export class NavController extends Ion {
return nav;
}
/**
* @private
*/
dismissPageChangeViews() {
this._views.forEach(view => {
if (view.data && view.data.dismissOnPageChange) {
view.dismiss();
}
});
}
/**
* @private
*/
@ -1819,20 +1765,6 @@ export class NavController extends Ion {
}
export interface NavOptions {
animate?: boolean;
animation?: string;
direction?: string;
duration?: number;
easing?: string;
keyboardClose?: boolean;
preload?: boolean;
transitionDelay?: number;
progressAnimation?: boolean;
climbNav?: boolean;
ev?: any;
}
const STATE_ACTIVE = 'active';
const STATE_INACTIVE = 'inactive';
const STATE_INIT_ENTER = 'init_enter';