diff --git a/src/components/app/app.ts b/src/components/app/app.ts
index c1adb6cda5..cc027d32bf 100644
--- a/src/components/app/app.ts
+++ b/src/components/app/app.ts
@@ -7,16 +7,14 @@ import {Platform} from '../../platform/platform';
/**
- * App utility service. Allows you to look up components that have been
- * registered using the [Id directive](../Id/).
+ * Ionic App utility service.
*/
@Injectable()
-export class IonicApp {
+export class App {
private _disTime: number = 0;
private _scrollTime: number = 0;
private _title: string = '';
private _titleSrv: Title = new Title();
- private _isProd: boolean = false;
private _rootNav: any = null;
private _appInjector: Injector;
@@ -48,23 +46,6 @@ export class IonicApp {
}
}
- /**
- * Returns if the app has been set to be in be in production mode or not.
- * Production mode can only be set within the config of `@App`. Defaults
- * to `false`.
- * @return {boolean}
- */
- isProd(): boolean {
- return this._isProd;
- }
-
- /**
- * @private
- */
- setProd(val: boolean) {
- this._isProd = !!val;
- }
-
/**
* @private
* Sets if the app is currently enabled or not, meaning if it's
@@ -80,9 +61,14 @@ export class IonicApp {
setEnabled(isEnabled: boolean, duration: number = 700) {
this._disTime = (isEnabled ? 0 : Date.now() + duration);
- if (duration > 32 || isEnabled) {
- // only do a click block if the duration is longer than XXms
- this._clickBlock.show(!isEnabled, duration + 64);
+ if (this._clickBlock) {
+ if (duration > 32) {
+ // only do a click block if the duration is longer than XXms
+ this._clickBlock.show(true, duration + 64);
+
+ } else {
+ this._clickBlock.show(false, 0);
+ }
}
}
diff --git a/src/components/app/structure.scss b/src/components/app/structure.scss
index e2191cfdb3..3b7a50600e 100644
--- a/src/components/app/structure.scss
+++ b/src/components/app/structure.scss
@@ -85,7 +85,7 @@ body {
text-size-adjust: none;
}
-ion-app,
+ion-app.app-init,
ion-nav,
ion-tabs {
position: absolute;
diff --git a/src/components/content/content.ts b/src/components/content/content.ts
index 1b906db387..99c6e07576 100644
--- a/src/components/content/content.ts
+++ b/src/components/content/content.ts
@@ -1,7 +1,7 @@
import {Component, ElementRef, Optional, NgZone, ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {Ion} from '../ion';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {nativeRaf, nativeTimeout, transitionEnd} from '../../util/dom';
@@ -28,10 +28,10 @@ import {ScrollView} from '../../util/scroll-view';
* you can use Angular's `@ViewChild` annotation:
*
* ```ts
- * import {ViewChild} from '@angular/core';
+ * import {Component, ViewChild} from '@angular/core';
* import {Content} from 'ionic-angular';
*
- * @Page({...}
+ * @Component({...})
* export class MyPage{
* @ViewChild(Content) content: Content;
*
@@ -67,7 +67,7 @@ export class Content extends Ion {
constructor(
private _elementRef: ElementRef,
private _config: Config,
- private _app: IonicApp,
+ private _app: App,
private _keyboard: Keyboard,
private _zone: NgZone,
@Optional() viewCtrl: ViewController
@@ -217,10 +217,10 @@ export class Content extends Ion {
* Scroll to the specified position.
*
* ```ts
- * import {ViewChild} from '@angular/core';
+ * import {Component, ViewChild} from '@angular/core';
* import {Content} from 'ionic-angular';
*
- * @Page({
+ * @Component({
* template: `
*
* `
@@ -248,10 +248,10 @@ export class Content extends Ion {
* Scroll to the top of the content component.
*
* ```ts
- * import {ViewChild} from '@angular/core';
+ * import {Component, ViewChild} from '@angular/core';
* import {Content} from 'ionic-angular';
*
- * @Page({
+ * @Component({
* template: `
*
* `
diff --git a/src/components/input/input-base.ts b/src/components/input/input-base.ts
index 07763786b5..ed06a3c4f7 100644
--- a/src/components/input/input-base.ts
+++ b/src/components/input/input-base.ts
@@ -5,7 +5,7 @@ import {Config} from '../../config/config';
import {Content} from '../content/content';
import {Form} from '../../util/form';
import {Item} from '../item/item';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {isTrueProperty} from '../../util/util';
import {Label} from '../label/label';
import {pointerCoord, hasPointerMoved, closest, copyInputAttributes} from '../../util/dom';
@@ -41,7 +41,7 @@ export class InputBase {
config: Config,
protected _form: Form,
protected _item: Item,
- protected _app: IonicApp,
+ protected _app: App,
protected _platform: Platform,
protected _elementRef: ElementRef,
protected _scrollView: Content,
diff --git a/src/components/input/input.ts b/src/components/input/input.ts
index c45572e0f8..386c460011 100644
--- a/src/components/input/input.ts
+++ b/src/components/input/input.ts
@@ -5,7 +5,7 @@ import {Config} from '../../config/config';
import {Content} from '../content/content';
import {Form} from '../../util/form';
import {InputBase} from './input-base';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Item} from '../item/item';
import {Label} from '../label/label';
import {NativeInput, NextInput} from './native-input';
@@ -79,7 +79,7 @@ export class TextInput extends InputBase {
config: Config,
form: Form,
@Optional() item: Item,
- app: IonicApp,
+ app: App,
platform: Platform,
elementRef: ElementRef,
@Optional() scrollView: Content,
@@ -170,7 +170,7 @@ export class TextArea extends InputBase {
config: Config,
form: Form,
@Optional() item: Item,
- app: IonicApp,
+ app: App,
platform: Platform,
elementRef: ElementRef,
@Optional() scrollView: Content,
diff --git a/src/components/modal/modal.ts b/src/components/modal/modal.ts
index 63a87b5b81..82bdb4f4ba 100644
--- a/src/components/modal/modal.ts
+++ b/src/components/modal/modal.ts
@@ -1,11 +1,12 @@
-import {Component, ComponentRef, DynamicComponentLoader, ElementRef, ViewChild, ViewContainerRef} from '@angular/core';
+import {Component, ComponentRef, DynamicComponentLoader, ViewChild, ViewContainerRef} from '@angular/core';
-import {windowDimensions} from '../../util/dom';
-import {pascalCaseToDashCase} from '../../util/util';
-import {NavParams} from '../nav/nav-params';
-import {ViewController} from '../nav/view-controller';
+import {addSelector} from '../../config/bootstrap';
import {Animation} from '../../animations/animation';
+import {NavParams} from '../nav/nav-params';
+import {pascalCaseToDashCase} from '../../util/util';
import {Transition, TransitionOptions} from '../../transitions/transition';
+import {ViewController} from '../nav/view-controller';
+import {windowDimensions} from '../../util/dom';
/**
* @name Modal
@@ -35,7 +36,7 @@ import {Transition, TransitionOptions} from '../../transitions/transition';
* ```ts
* import {Page, Modal, NavController, NavParams} from 'ionic-angular';
*
- * @Page(...)
+ * @Component(...)
* class HomePage {
*
* constructor(nav: NavController) {
@@ -49,7 +50,7 @@ import {Transition, TransitionOptions} from '../../transitions/transition';
*
* }
*
- * @Page(...)
+ * @Component(...)
* class Profile {
*
* constructor(params: NavParams) {
@@ -65,9 +66,10 @@ import {Transition, TransitionOptions} from '../../transitions/transition';
* modal.
*
* ```ts
- * import {Page, Modal, NavController, ViewController} from 'ionic-angular';
+ * import {Component} from '@angular/core';
+ * import {Modal, NavController, ViewController} from 'ionic-angular';
*
- * @Page(...)
+ * @Component(...)
* class HomePage {
*
* constructor(nav: NavController) {
@@ -89,7 +91,7 @@ import {Transition, TransitionOptions} from '../../transitions/transition';
*
* }
*
- * @Page(...)
+ * @Component(...)
* class Profile {
*
* constructor(viewCtrl: ViewController) {
@@ -140,7 +142,7 @@ export class Modal extends ViewController {
let originalNgAfterViewInit = this.instance.ngAfterViewInit;
this.instance.ngAfterViewInit = () => {
- if ( originalNgAfterViewInit ) {
+ if (originalNgAfterViewInit) {
originalNgAfterViewInit();
}
this.instance.loadComponent().then( (componentRef: ComponentRef) => {
@@ -163,11 +165,13 @@ export class ModalCmp {
@ViewChild('viewport', {read: ViewContainerRef}) viewport: ViewContainerRef;
- constructor(protected _eleRef: ElementRef, protected _loader: DynamicComponentLoader, protected _navParams: NavParams, protected _viewCtrl: ViewController) {
- }
+ constructor(protected _loader: DynamicComponentLoader, protected _navParams: NavParams) {}
loadComponent(): Promise> {
- return this._loader.loadNextToLocation(this._navParams.data.componentType, this.viewport).then(componentRef => {
+ let componentType = this._navParams.data.componentType;
+ addSelector(componentType, 'ion-page');
+
+ return this._loader.loadNextToLocation(componentType, this.viewport).then(componentRef => {
return componentRef;
});
}
diff --git a/src/components/modal/test/modal.spec.ts b/src/components/modal/test/modal.spec.ts
index a7fa498d34..725b1b1cf5 100644
--- a/src/components/modal/test/modal.spec.ts
+++ b/src/components/modal/test/modal.spec.ts
@@ -1,4 +1,5 @@
-import {Modal, ModalCmp, Page, NavController, ViewController} from '../../../../src';
+import {Component} from '@angular/core';
+import {Modal, ModalCmp, NavController, ViewController} from '../../../../src';
export function run() {
describe('Modal', () => {
@@ -51,19 +52,19 @@ export function run() {
it('should return a componentRef object after loading component', (done) => {
// arrange
- let mockLoader = {
+ let mockLoader: any = {
loadNextToLocation: () => {}
};
- let mockNavParams = {
+ let mockNavParams: any = {
data: {
- componentType: "myComponentType"
+ componentType: function mockComponentType(){}
}
};
let mockComponentRef = {};
spyOn(mockLoader, "loadNextToLocation").and.returnValue(Promise.resolve(mockComponentRef));
- let modalCmp = new ModalCmp(null, mockLoader, mockNavParams, null);
- modalCmp.viewport = "mockViewport";
+ let modalCmp = new ModalCmp(mockLoader, mockNavParams);
+ modalCmp.viewport = "mockViewport";
// act
modalCmp.loadComponent().then(loadedComponentRef => {
@@ -91,7 +92,7 @@ let componentToPresentSpy = {
_ionicProjectContent: () => {},
};
-@Page({
+@Component({
template: ``
})
class ComponentToPresent{
diff --git a/src/components/nav/nav-controller.ts b/src/components/nav/nav-controller.ts
index 34d3583866..a8bdab35a0 100644
--- a/src/components/nav/nav-controller.ts
+++ b/src/components/nav/nav-controller.ts
@@ -1,11 +1,12 @@
-import {ViewContainerRef, DynamicComponentLoader, provide, ReflectiveInjector, ResolvedReflectiveProvider, ElementRef, NgZone, Renderer, Type} from '@angular/core';
+import {ViewContainerRef, DynamicComponentLoader, provide, ReflectiveInjector, ResolvedReflectiveProvider, ElementRef, NgZone, Renderer, Type, EventEmitter} from '@angular/core';
+import {addSelector} from '../../config/bootstrap';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {Ion} from '../ion';
-import {IonicApp} from '../app/app';
+import {isBlank, pascalCaseToDashCase} from '../../util/util';
import {Keyboard} from '../../util/keyboard';
import {NavParams} from './nav-params';
-import {pascalCaseToDashCase, isBlank} from '../../util/util';
import {MenuController} from '../menu/menu-controller';
import {NavPortal} from './nav-portal';
import {SwipeBackGesture} from './swipe-back';
@@ -59,12 +60,9 @@ import {ViewController} from './view-controller';
*
*
* ## Page creation
- * _For more information on the `@Page` decorator see the [@Page API
- * reference](../../../decorators/Page/)._
- *
* Pages are created when they are added to the navigation stack. For methods
* like [push()](#push), the NavController takes any component class that is
- * decorated with `@Page` as its first argument. The NavController then
+ * decorated with `@Component` as its first argument. The NavController then
* compiles that component, adds it to the app and animates it into view.
*
* By default, pages are cached and left in the DOM if they are navigated away
@@ -75,10 +73,12 @@ import {ViewController} from './view-controller';
*
* ## Lifecycle events
* Lifecycle events are fired during various stages of navigation. They can be
- * defined in any `@Page` decorated component class.
+ * defined in any component type which is pushed/popped from a `NavController`.
*
* ```ts
- * @Page({
+ * import {Component} from '@angular/core';
+ *
+ * @Component({
* template: 'Hello World'
* })
* class HelloWorld {
@@ -171,6 +171,14 @@ export class NavController extends Ion {
protected _trnsTime: number = 0;
protected _views: Array = [];
+ pageDidLoad: EventEmitter;
+ pageWillEnter: EventEmitter;
+ pageDidEnter: EventEmitter;
+ pageWillLeave: EventEmitter;
+ pageDidLeave: EventEmitter;
+ pageWillUnload: EventEmitter;
+ pageDidUnload: EventEmitter;
+
/**
* @private
*/
@@ -203,7 +211,7 @@ export class NavController extends Ion {
constructor(
parent: any,
- protected _app: IonicApp,
+ protected _app: App,
config: Config,
protected _keyboard: Keyboard,
elementRef: ElementRef,
@@ -227,6 +235,14 @@ export class NavController extends Ion {
this.providers = ReflectiveInjector.resolve([
provide(NavController, {useValue: this})
]);
+
+ this.pageDidLoad = new EventEmitter();
+ this.pageWillEnter = new EventEmitter();
+ this.pageDidEnter = new EventEmitter();
+ this.pageWillLeave = new EventEmitter();
+ this.pageDidLeave = new EventEmitter();
+ this.pageWillUnload = new EventEmitter();
+ this.pageDidUnload = new EventEmitter();
}
/**
@@ -508,6 +524,7 @@ export class NavController extends Ion {
animation: enteringView.getTransitionName('back')
});
+ // present() always uses the root nav
// start the transition
return rootNav._insertViews(-1, [enteringView], opts);
}
@@ -819,9 +836,11 @@ export class NavController extends Ion {
// Tabs can be a parent, but it is not a collection of views
// only we're looking for an actual NavController w/ stack of views
leavingView.fireWillLeave();
+ this.pageWillLeave.emit(leavingView);
return parentNav.pop(opts).then((rtnVal: boolean) => {
leavingView.fireDidLeave();
+ this.pageDidLeave.emit(leavingView);
return rtnVal;
});
}
@@ -919,6 +938,7 @@ export class NavController extends Ion {
// the first view to be removed, it should init leave
view.state = STATE_INIT_LEAVE;
view.fireWillUnload();
+ this.pageWillUnload.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
@@ -952,7 +972,9 @@ 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.pageWillLeave.emit(view);
view.fireDidLeave();
+ this.pageDidLeave.emit(view);
this._views.splice(this.indexOf(view), 1);
view.destroy();
});
@@ -987,6 +1009,7 @@ export class NavController extends Ion {
// if no entering view then create a bogus one
enteringView = new ViewController();
enteringView.fireLoaded();
+ this.pageDidLoad.emit(enteringView);
}
/* Async steps to complete a transition
@@ -1043,6 +1066,7 @@ export class NavController extends Ion {
this.loadPage(enteringView, null, opts, () => {
enteringView.fireLoaded();
+ this.pageDidLoad.emit(enteringView);
this._postRender(transId, enteringView, leavingView, isAlreadyTransitioning, opts, done);
});
}
@@ -1102,12 +1126,14 @@ export class NavController extends Ion {
// only fire entering lifecycle if the leaving
// view hasn't explicitly set not to
enteringView.fireWillEnter();
+ this.pageWillEnter.emit(enteringView);
}
if (enteringView.fireOtherLifecycles) {
// only fire leaving lifecycle if the entering
// view hasn't explicitly set not to
leavingView.fireWillLeave();
+ this.pageWillLeave.emit(leavingView);
}
} else {
@@ -1214,12 +1240,14 @@ export class NavController extends Ion {
// only fire entering lifecycle if the leaving
// view hasn't explicitly set not to
enteringView.fireDidEnter();
+ this.pageDidEnter.emit(enteringView);
}
if (enteringView.fireOtherLifecycles) {
// only fire leaving lifecycle if the entering
// view hasn't explicitly set not to
leavingView.fireDidLeave();
+ this.pageDidLeave.emit(leavingView);
}
}
@@ -1422,21 +1450,25 @@ export class NavController extends Ion {
return;
}
+ // add more providers to just this page
let providers = this.providers.concat(ReflectiveInjector.resolve([
provide(ViewController, {useValue: view}),
provide(NavParams, {useValue: view.getNavParams()})
]));
+ // automatically set "ion-page" selector
+ addSelector(view.componentType, 'ion-page');
+
// load the page component inside the nav
this._loader.loadNextToLocation(view.componentType, this._viewport, providers).then(component => {
-
+
// a new ComponentRef has been created
// set the ComponentRef's instance to its ViewController
view.setInstance(component.instance);
-
+
// the component has been loaded, so call the view controller's loaded method to load any dependencies into the dom
view.loaded( () => {
-
+
// the ElementRef of the actual ion-page created
let pageElementRef = component.location;
diff --git a/src/components/nav/nav-portal.ts b/src/components/nav/nav-portal.ts
index d5e25b1584..0000702832 100644
--- a/src/components/nav/nav-portal.ts
+++ b/src/components/nav/nav-portal.ts
@@ -1,6 +1,6 @@
import {Directive, ElementRef, Optional, NgZone, Renderer, DynamicComponentLoader, ViewContainerRef} from '@angular/core';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {NavController} from './nav-controller';
@@ -16,7 +16,7 @@ export class NavPortal extends NavController {
constructor(
@Optional() viewCtrl: ViewController,
@Optional() parent: NavController,
- app: IonicApp,
+ app: App,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
diff --git a/src/components/nav/nav.ts b/src/components/nav/nav.ts
index 3a0f7361bb..3ddb6fc92c 100644
--- a/src/components/nav/nav.ts
+++ b/src/components/nav/nav.ts
@@ -1,6 +1,6 @@
import {Component, ElementRef, ViewContainerRef, DynamicComponentLoader, Input, Optional, NgZone, Renderer, Type, ViewChild, ViewEncapsulation, AfterViewInit} from '@angular/core';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {isTrueProperty} from '../../util/util';
@@ -28,15 +28,18 @@ import {ViewController} from './view-controller';
*
* @usage
* ```ts
- * import {GettingStartedPage} from 'getting-started';
- * @App({
- * template: ``
+ * import {Component} from '@angular/core';
+ * import {ionicBootstrap} from 'ionic-angular';
+ * import {GettingStartedPage} from './getting-started';
+ *
+ * @Component({
+ * template: ``
* })
* class MyApp {
- * constructor(){
- * this.rootPage = GettingStartedPage;
- * }
+ * root = GettingStartedPage;
* }
+ *
+ * ionicBootstrap(MyApp);
* ```
*
* ### Back Navigation
@@ -117,7 +120,7 @@ export class Nav extends NavController implements AfterViewInit {
constructor(
@Optional() viewCtrl: ViewController,
@Optional() parent: NavController,
- app: IonicApp,
+ app: App,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
diff --git a/src/components/navbar/navbar.ts b/src/components/navbar/navbar.ts
index 71b88b1721..c71e276a4e 100644
--- a/src/components/navbar/navbar.ts
+++ b/src/components/navbar/navbar.ts
@@ -4,7 +4,7 @@ import {Ion} from '../ion';
import {Icon} from '../icon/icon';
import {ToolbarBase} from '../toolbar/toolbar';
import {Config} from '../../config/config';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {isTrueProperty} from '../../util/util';
import {ViewController} from '../nav/view-controller';
import {NavController} from '../nav/nav-controller';
@@ -134,7 +134,7 @@ export class Navbar extends ToolbarBase {
}
constructor(
- private _app: IonicApp,
+ private _app: App,
@Optional() viewCtrl: ViewController,
elementRef: ElementRef,
config: Config,
diff --git a/src/components/tabs/tab.ts b/src/components/tabs/tab.ts
index 58b32f0f2c..91401e927e 100644
--- a/src/components/tabs/tab.ts
+++ b/src/components/tabs/tab.ts
@@ -1,6 +1,6 @@
import {Component, Inject, forwardRef, ElementRef, NgZone, Renderer, DynamicComponentLoader, ViewContainerRef, ViewChild, Type, ViewEncapsulation, ChangeDetectorRef, EventEmitter, Input, Output} from '@angular/core';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {isTrueProperty} from '../../util/util';
import {Keyboard} from '../../util/keyboard';
@@ -208,7 +208,7 @@ export class Tab extends NavController {
constructor(
@Inject(forwardRef(() => Tabs)) parentTabs: Tabs,
- app: IonicApp,
+ app: App,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
diff --git a/src/components/tabs/tabs.ts b/src/components/tabs/tabs.ts
index 14a3e25041..fd645debf6 100644
--- a/src/components/tabs/tabs.ts
+++ b/src/components/tabs/tabs.ts
@@ -1,6 +1,6 @@
import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, ViewChild, ViewChildren, EventEmitter, Output, Input, Renderer, ViewEncapsulation} from '@angular/core';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {Tab} from './tab';
import {TabButton} from './tab-button';
@@ -49,7 +49,7 @@ import {isBlank, isTrueProperty} from '../../util/util';
*
* @usage
*
- * You can add a basic tabs template to a `@Page` using the following
+ * You can add a basic tabs template to a `@Component` using the following
* template:
*
* ```html
@@ -63,7 +63,7 @@ import {isBlank, isTrueProperty} from '../../util/util';
* Where `tab1Root`, `tab2Root`, and `tab3Root` are each a page:
*
*```ts
- * @Page({
+ * @Component({
* templateUrl: 'build/pages/tabs/tabs.html'
* })
* export class TabsPage {
@@ -223,7 +223,7 @@ export class Tabs extends Ion {
constructor(
@Optional() parent: NavController,
@Optional() viewCtrl: ViewController,
- private _app: IonicApp,
+ private _app: App,
private _config: Config,
private _elementRef: ElementRef,
private _platform: Platform,
diff --git a/src/components/tap-click/tap-click.ts b/src/components/tap-click/tap-click.ts
index 33ee84c892..056747748f 100644
--- a/src/components/tap-click/tap-click.ts
+++ b/src/components/tap-click/tap-click.ts
@@ -1,6 +1,6 @@
import {Injectable, NgZone} from '@angular/core';
-import {IonicApp} from '../app/app';
+import {App} from '../app/app';
import {Config} from '../../config/config';
import {pointerCoord, hasPointerMoved} from '../../util/dom';
import {Activator} from './activator';
@@ -22,7 +22,7 @@ export class TapClick {
constructor(
config: Config,
- private app: IonicApp,
+ private app: App,
private zone: NgZone
) {
let self = this;
diff --git a/src/config/bootstrap.ts b/src/config/bootstrap.ts
index 2226bfbdb5..3d79c87699 100644
--- a/src/config/bootstrap.ts
+++ b/src/config/bootstrap.ts
@@ -1,36 +1,81 @@
-import {provide, Provider, ComponentRef, NgZone} from '@angular/core';
+import {bootstrap} from '@angular/platform-browser-dynamic';
+import {Directive, ReflectiveInjector, Renderer, enableProdMode, ViewContainerRef, provide, PLATFORM_DIRECTIVES, ComponentRef, NgZone, DynamicComponentLoader} from '@angular/core';
import {ROUTER_PROVIDERS} from '@angular/router';
import {LocationStrategy, HashLocationStrategy} from '@angular/common';
import {HTTP_PROVIDERS} from '@angular/http';
+import {App} from '../components/app/app';
import {ClickBlock} from '../util/click-block';
import {Config} from './config';
import {Events} from '../util/events';
import {FeatureDetect} from '../util/feature-detect';
import {Form} from '../util/form';
-import {IonicApp} from '../components/app/app';
+import {IONIC_DIRECTIVES} from './directives';
+import {isPresent} from '../util/util';
import {Keyboard} from '../util/keyboard';
import {MenuController} from '../components/menu/menu-controller';
+import {nativeTimeout, closest} from '../util/dom';
import {NavRegistry} from '../components/nav/nav-registry';
import {Platform} from '../platform/platform';
-import {ready, closest} from '../util/dom';
import {ScrollView} from '../util/scroll-view';
import {TapClick} from '../components/tap-click/tap-click';
import {Translate} from '../translation/translate';
+const _reflect: any = Reflect;
-/**
- * @private
- */
-export function ionicProviders(args: any = {}) {
- let platform = new Platform();
- let navRegistry = new NavRegistry(args.pages);
- var config = args.config;
+export function ionicBootstrap(appRootComponent: any, customProviders?: Array, config?: any): Promise> {
+ // get all Ionic Providers
+ let providers = ionicProviders(customProviders, config);
+ // automatically set "ion-app" selector to users root component
+ addSelector(appRootComponent, 'ion-app');
+
+ // call angular bootstrap
+ return bootstrap(appRootComponent, providers).then(ngComponentRef => {
+ // ionic app has finished bootstrapping
+ return ionicPostBootstrap(ngComponentRef);
+ });
+}
+
+
+export function ionicPostBootstrap(ngComponentRef: ComponentRef): ComponentRef {
+ //ngComponentRef.injector.get(TapClick);
+ let app: App = ngComponentRef.injector.get(App);
+ app.setAppInjector(ngComponentRef.injector);
+
+ // prepare platform ready
+ let platform: Platform = ngComponentRef.injector.get(Platform);
+ platform.setZone(ngComponentRef.injector.get(NgZone));
+ platform.prepareReady();
+
+ // TODO: Use Renderer
+ ngComponentRef.location.nativeElement.classList.add('app-init');
+
+ return ngComponentRef;
+}
+
+
+export function ionicProviders(customProviders?: Array, config?: any): any[] {
+ // add custom providers to Ionic's dev
+ let directives = IONIC_DIRECTIVES;
+ if (customProviders) {
+ directives.push(customProviders);
+ }
+
+ // create an instance of Config
if (!(config instanceof Config)) {
config = new Config(config);
}
+ // enable production mode if config set to true
+ if (config.getBoolean('prodMode')) {
+ enableProdMode();
+ }
+
+ // create an instance of Platform
+ let platform = new Platform();
+
+ // initialize platform
platform.setUrl(window.location.href);
platform.setUserAgent(window.navigator.userAgent);
platform.setNavigatorPlatform(window.navigator.platform);
@@ -38,7 +83,6 @@ export function ionicProviders(args: any = {}) {
config.setPlatform(platform);
let clickBlock = new ClickBlock();
-
let events = new Events();
let featureDetect = new FeatureDetect();
@@ -46,51 +90,43 @@ export function ionicProviders(args: any = {}) {
bindEvents(window, document, platform, events);
return [
- IonicApp,
+ App,
provide(ClickBlock, {useValue: clickBlock}),
provide(Config, {useValue: config}),
- provide(Platform, {useValue: platform}),
- provide(FeatureDetect, {useValue: featureDetect}),
provide(Events, {useValue: events}),
- provide(NavRegistry, {useValue: navRegistry}),
- TapClick,
+ provide(FeatureDetect, {useValue: featureDetect}),
Form,
Keyboard,
MenuController,
+ NavRegistry,
+ provide(Platform, {useValue: platform}),
Translate,
+ TapClick,
+ provide(PLATFORM_DIRECTIVES, {useValue: [directives], multi: true}),
ROUTER_PROVIDERS,
provide(LocationStrategy, {useClass: HashLocationStrategy}),
HTTP_PROVIDERS,
];
}
-/**
- * @private
- */
-export function postBootstrap(appRef: ComponentRef, prodMode: boolean) {
- appRef.injector.get(TapClick);
- let app: IonicApp = appRef.injector.get(IonicApp);
- let platform: Platform = appRef.injector.get(Platform);
- platform.setZone(appRef.injector.get(NgZone));
- platform.prepareReady();
- app.setProd(prodMode);
- app.setAppInjector(appRef.injector);
-}
-
-function setupDom(window, document, config, platform, clickBlock, featureDetect) {
+function setupDom(window: Window, document: Document, config: Config, platform: Platform, clickBlock: ClickBlock, featureDetect: FeatureDetect) {
let bodyEle = document.body;
let mode = config.get('mode');
// if dynamic mode links have been added the fire up the correct one
let modeLinkAttr = mode + '-href';
- let linkEle = document.head.querySelector('link[' + modeLinkAttr + ']');
+ let linkEle = document.head.querySelector('link[' + modeLinkAttr + ']');
if (linkEle) {
let href = linkEle.getAttribute(modeLinkAttr);
linkEle.removeAttribute(modeLinkAttr);
linkEle.href = href;
}
+ let headStyle = document.createElement('style');
+ headStyle.innerHTML = 'ion-app{display:none}';
+ document.head.appendChild(headStyle);
+
// set the mode class name
// ios/md/wp
bodyEle.classList.add(mode);
@@ -122,10 +158,6 @@ function setupDom(window, document, config, platform, clickBlock, featureDetect)
bodyEle.classList.add('enable-hover');
}
- if (config.get('clickBlock')) {
- clickBlock.enable();
- }
-
// run feature detection tests
featureDetect.run(window, document);
}
@@ -134,7 +166,7 @@ function setupDom(window, document, config, platform, clickBlock, featureDetect)
/**
* Bind some global events and publish on the 'app' channel
*/
-function bindEvents(window, document, platform, events) {
+function bindEvents(window: Window, document: Document, platform: Platform, events: Events) {
window.addEventListener('online', (ev) => {
events.publish('app:online', ev);
}, false);
@@ -150,10 +182,10 @@ function bindEvents(window, document, platform, events) {
// When that status taps, we respond
window.addEventListener('statusTap', (ev) => {
// TODO: Make this more better
- var el = document.elementFromPoint(platform.width() / 2, platform.height() / 2);
+ let el = document.elementFromPoint(platform.width() / 2, platform.height() / 2);
if (!el) { return; }
- var content = closest(el, 'scroll-content');
+ let content = closest(el, 'scroll-content');
if (content) {
var scroll = new ScrollView(content);
scroll.scrollTo(0, 0, 300);
@@ -161,9 +193,22 @@ function bindEvents(window, document, platform, events) {
});
// start listening for resizes XXms after the app starts
- setTimeout(function() {
- window.addEventListener('resize', function() {
+ nativeTimeout(() => {
+ window.addEventListener('resize', () => {
platform.windowResize();
});
}, 2000);
}
+
+/**
+ * @private
+ */
+export function addSelector(type: any, selector: string) {
+ if (type) {
+ let annotations = _reflect.getMetadata('annotations', type);
+ if (annotations && !annotations[0].selector) {
+ annotations[0].selector = selector;
+ _reflect.defineMetadata('annotations', annotations, type);
+ }
+ }
+}
diff --git a/src/config/test/config.spec.ts b/src/config/test/config.spec.ts
index 65160debcc..ae83b77b53 100644
--- a/src/config/test/config.spec.ts
+++ b/src/config/test/config.spec.ts
@@ -80,7 +80,7 @@ export function run() {
let userConfig = new Config({
mode: 'configInstance'
})
- let providers = ionicProviders({config:userConfig});
+ let providers = ionicProviders(null, userConfig);
let config = providers.find(provider => provider.useValue instanceof Config).useValue;
@@ -88,9 +88,9 @@ export function run() {
});
it('should create new Config instance from config object in ionicProviders', () => {
- let providers = ionicProviders({config: {
+ let providers = ionicProviders(null, {
mode: 'configObj'
- }});
+ });
let config = providers.find(provider => provider.useValue instanceof Config).useValue;
diff --git a/src/decorators/app.ts b/src/decorators/app.ts
deleted file mode 100644
index c6f2efecaf..0000000000
--- a/src/decorators/app.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import {Component, ChangeDetectionStrategy, ViewEncapsulation, enableProdMode, Type, provide, PLATFORM_DIRECTIVES} from '@angular/core';
-import {bootstrap} from '@angular/platform-browser-dynamic';
-import {ionicProviders, postBootstrap} from '../config/bootstrap';
-import {IONIC_DIRECTIVES} from '../config/directives';
-
-const _reflect: any = Reflect;
-
-export interface AppMetadata {
- prodMode?: boolean;
- selector?: string;
- inputs?: string[];
- outputs?: string[];
- properties?: string[];
- events?: string[];
- host?: {
- [key: string]: string;
- };
- providers?: any[];
- directives?: Array;
- pipes?: Array;
- exportAs?: string;
- queries?: {
- [key: string]: any;
- };
- template?: string;
- templateUrl?: string;
- moduleId?: string;
- styleUrls?: string[];
- styles?: string[];
- changeDetection?: ChangeDetectionStrategy;
- encapsulation?: ViewEncapsulation;
- config?: any;
-}
-
-/**
-* @name App
-* @description
-* App is an Ionic decorator that bootstraps an application. It can be passed a
-* number of arguments that act as global config variables for the app.
-* `@App` is similar to Angular's `@Component` in which it can accept a `template`
-* property that has an inline template, or a `templateUrl` property that points
-* to an external html template. The `@App` decorator runs the Angular bootstrapping
-* process automatically, however you can bootstrap your app separately if you prefer.
-* Additionally, `@App` will automatically bootstrap with all of Ionic's
-* core components, meaning they won't all have to be individually imported and added
-* to each component's `directives` property.
-*
-* @usage
-* ```ts
-* import {App} from 'ionic-angular';
-*
-* @App({
-* templateUrl: 'app/app.html',
-* providers: [DataService]
-* })
-*
-* export class MyApp{
-* // Anything we would want to do at the root of our app
-* }
-* ```
-*
-* @property {object} [config] - the app's {@link /docs/v2/api/config/Config/ Config} object.
-* @property {boolean} [prodMode] - Enable Angular's production mode, which turns off assertions and other checks within the framework. Additionally, this config sets the return value of `isProd()` which is on the `IonicApp` instance. Defaults to `false`.
-* @property {array} [pipes] - any pipes for your app.
-* @property {array} [providers] - any providers for your app.
-* @property {string} [template] - the template to use for the app root.
-* @property {string} [templateUrl] - a relative URL pointing to the template to use for the app root.
-*/
-export function App(args: AppMetadata = {}) {
-
- return function(cls) {
- // get current annotations
- let annotations = _reflect.getMetadata('annotations', cls) || [];
-
- args.selector = 'ion-app';
-
- // if no template was provided, default so it has a root
- if (!args.templateUrl && !args.template) {
- args.template = '';
- }
-
- // create @Component
- annotations.push(new Component(args));
-
- // redefine with added annotations
- _reflect.defineMetadata('annotations', annotations, cls);
-
- // define array of bootstrap providers
- let providers = ionicProviders(args).concat(args.providers || []);
-
- // auto add Ionic directives
- let directives = args.directives ? args.directives.concat(IONIC_DIRECTIVES) : IONIC_DIRECTIVES;
-
- // automatically provide all of Ionic's directives to every component
- providers.push(provide(PLATFORM_DIRECTIVES, {useValue: [directives], multi: true}));
-
- if (args.prodMode) {
- enableProdMode();
- }
-
- bootstrap(cls, providers).then(appRef => {
- postBootstrap(appRef, args.prodMode);
- });
-
- return cls;
- };
-}
diff --git a/src/decorators/page.ts b/src/decorators/page.ts
index d70e29520d..162312f581 100644
--- a/src/decorators/page.ts
+++ b/src/decorators/page.ts
@@ -28,41 +28,13 @@ export interface PageMetadata {
}
/**
- * @name Page
- * @description
- *
- * The Page decorator indicates that the decorated class is an Ionic
- * navigation component, meaning it can be navigated to using a
- * [NavController](../../nav/NavController).
- *
- * Since the app has already been bootstrapped with Ionic's core directives, it
- * is not needed to include `IONIC_DIRECTIVES` in the directives property. Additionally,
- * Angular's [CORE_DIRECTIVES](https://angular.io/docs/ts/latest/api/common/CORE_DIRECTIVES-let.html)
- * and [FORM_DIRECTIVES](https://angular.io/docs/ts/latest/api/common/FORM_DIRECTIVES-let.html),
- * are also already provided, so you only need to supply any custom components and directives
- * to your pages:
- *
- * @usage
- *
- * ```ts
- * @Page({
- * template: `
- *
- * I am a page!
- *
- * `
- * })
- * class MyPage {}
- * ```
- *
- * Pages have their content automatically wrapped in ``, so although
- * you may see these tags if you inspect your markup, you don't need to include
- * them in your templates.
- *
- * For more information on how pages are created, see the [NavController API Docs](../../components/nav/NavController/#creating_pages)
+ * @private
*/
export function Page(config: PageMetadata) {
return function(cls) {
+ // deprecated warning: added beta.8 2016-05-27
+ console.warn('@Page decorator has been deprecated. Please use Angular\'s @Component instead.\nimport {Component} from \'@angular/core\';');
+
config.selector = 'ion-page';
config.host = config.host || {};
config.host['[hidden]'] = '_hidden';
diff --git a/src/index.ts b/src/index.ts
index 65c7635b7f..78d8f01acf 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -3,7 +3,6 @@ export * from './config/bootstrap';
export * from './config/config';
export * from './config/directives';
-export * from './decorators/app';
export * from './decorators/page';
export * from './components';