Files
Adam Bradley 9d2570d2e5 router updates
2015-07-08 02:18:25 -05:00

236 lines
6.3 KiB
TypeScript

import {bootstrap, Compiler, ElementRef, NgZone, bind, ViewRef} from 'angular2/angular2';
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
import {NgZone} from 'angular2/src/core/zone/ng_zone';
import {IonicRouter} from '../../routing/router';
import {IonicConfig} from '../../config/config';
import {Platform} from '../../platform/platform';
import {Registry} from '../../registry';
import * as util from '../../util/util';
// injectables
import {ActionMenu} from '../action-menu/action-menu';
import {Modal} from '../modal/modal';
export class IonicApp {
constructor() {
this.overlays = [];
// Our component registry map
this.components = {};
this._activeViewId = null;
}
load(appRef) {
this.ref(appRef);
this.zone(this.injector().get(NgZone));
}
ref(val) {
if (arguments.length) {
this._ref = val;
}
return this._ref;
}
injector() {
return this._ref.injector;
}
zone(val) {
if (arguments.length) {
this._zone = val;
}
return this._zone;
}
stateChange(type, activeView) {
if (this._activeViewId !== activeView.id) {
this.router.stateChange(type, activeView);
this._activeViewId = activeView.id;
}
}
/**
* Register a known component with a key, for easy lookups later.
*/
register(key, component) {
this.components[key] = component;
console.log('App: Registered component', key, component);
// TODO(mlynch): We need to track the lifecycle of this component to remove it onDehydrate
}
/**
* Get the component for the given key.
*/
getComponent(key) {
return this.components[key];
}
/**
* Create and append the given component into the root
* element of the app.
*
* @param Component the ComponentType to create and insert
* @return Promise that resolves with the ContainerRef created
*/
appendComponent(ComponentType: Type, context=null) {
return new Promise((resolve, reject) => {
let injector = this.injector();
let compiler = injector.get(Compiler);
let viewMngr = injector.get(AppViewManager);
let rootComponentRef = this._ref._hostComponent;
let viewContainerLocation = rootComponentRef.location;
compiler.compileInHost(ComponentType).then(protoViewRef => {
let atIndex = 0;
let hostViewRef = viewMngr.createViewInContainer(
viewContainerLocation,
atIndex,
protoViewRef,
null,
injector);
hostViewRef.elementRef = new ElementRef(hostViewRef, 0, viewMngr._renderer);
hostViewRef.instance = viewMngr.getComponent(hostViewRef.elementRef);
util.extend(hostViewRef.instance, context);
hostViewRef.dispose = () => {
viewMngr.destroyViewInContainer(viewContainerLocation, 0, 0, hostViewRef.viewRef);
};
resolve(hostViewRef);
}).catch(err => {
console.error('appendComponent:', err);
reject(err);
});
});
}
applyBodyCss(bodyClassList, platform, config) {
let versions = platform.versions();
platform.platforms().forEach(platformName => {
// platform-ios
let platformClass = 'platform-' + platformName;
bodyClassList.add(platformClass);
let platformVersion = versions[platformName];
if (platformVersion) {
// platform-ios_8
platformClass += '_' + platformVersion.major;
bodyClassList.add(platformClass);
// platform-ios_8_3
bodyClassList.add(platformClass + '_' + platformVersion.minor);
}
});
bodyClassList.add('mode-' + config.setting('mode'));
}
isRTL(val) {
if (arguments.length) {
this._rtl = val;
}
return this._rtl;
}
}
function initApp(window, document, config) {
// create the base IonicApp
let app = new IonicApp();
app.isRTL(document.documentElement.getAttribute('dir') == 'rtl');
// load all platform data
// Platform is a global singleton
Platform.url(window.location.href);
Platform.userAgent(window.navigator.userAgent);
Platform.width(window.innerWidth);
Platform.height(window.innerHeight);
Platform.load(config);
return app;
}
export function ionicBootstrap(ComponentType, config, router) {
return new Promise((resolve, reject) => {
try {
// get the user config, or create one if wasn't passed in
config = config || new IonicConfig();
// create the base IonicApp
let app = initApp(window, document, config);
// copy default platform settings into the user config platform settings
// user config platform settings should override default platform settings
config.setPlatform(Platform);
// make the config global
IonicConfig.global = config;
// config and platform settings have been figured out
// apply the correct CSS to the app
app.applyBodyCss(document.body.classList, Platform, config);
// prepare the ready promise to fire....when ready
Platform.prepareReady(config);
// setup router
router = router || new IonicRouter();
router.app(app);
// TODO: don't wire these together
app.router = router;
// TODO: probs need a better way to inject global injectables
let actionMenu = new ActionMenu(app);
let modal = new Modal(app);
// add injectables that will be available to all child components
let injectableBindings = [
bind(IonicApp).toValue(app),
bind(IonicConfig).toValue(config),
bind(IonicRouter).toValue(router),
bind(ActionMenu).toValue(actionMenu),
bind(Modal).toValue(modal)
];
bootstrap(ComponentType, injectableBindings).then(appRef => {
app.load(appRef);
router.init(window);
// resolve that the app has loaded
resolve(app);
}).catch(err => {
console.error('ionicBootstrap', err);
reject(err);
});
} catch (err) {
console.error('ionicBootstrap', err);
reject(err);
}
});
}
export function load(app) {
if (!app) {
console.error('Invalid app module');
} else if (!app.main) {
console.error('App module missing main()');
} else {
app.main(ionicBootstrap);
}
}