diff --git a/ionic/components/modal/modal.js b/ionic/components/modal/modal.js
index 30c25d453b..8af7600869 100644
--- a/ionic/components/modal/modal.js
+++ b/ionic/components/modal/modal.js
@@ -1,14 +1,14 @@
import {DynamicComponentLoader, ElementRef, ComponentRef, onDestroy, DomRenderer} from 'angular2/angular2';
+import {bind, Injector} from 'angular2/di';
+import {Promise} from 'angular2/src/facade/async';
+import {isPresent, Type} from 'angular2/src/facade/lang';
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
-
-import {Nav} from 'ionic/ionic';
+import {Parent} from 'angular2/src/core/annotations_impl/visibility';
import {raf, ready} from 'ionic/util/dom'
-import {NavController, NavParams, NavbarTemplate, Navbar, Content} from 'ionic/ionic';
-
@Component({
selector: 'ion-modal-wrapper'
})
@@ -32,6 +32,7 @@ class ModalWrapper {
}
}
+/*
@Component({
selector: 'ion-modal'
})
@@ -39,126 +40,158 @@ class ModalWrapper {
template: `
-
`,
- directives: [Nav],
+ directives: []
})
+*/
export class Modal {
//compiler: Compiler;
- constructor(loader: DynamicComponentLoader, domRenderer: DomRenderer, elementRef: ElementRef) {
+ constructor(type: Type, loader: DynamicComponentLoader, injector: Injector, domRenderer: DomRenderer, elementRef: ElementRef) {
+ this.modalType = type;
this.componentLoader = loader;
this.domRenderer = domRenderer;
+ this.injector = injector;
this.element = elementRef.domElement;
this.elementRef = elementRef;
-
- this.initial = ModalFirstPage
}
- static create() {
- var m = new Modal();
- return m;
+ static create(modalType: Type, loader: ComponentLoader, injector: Injector, renderer: DomRenderer, elementRef: ElementRef) {
+ console.log('Create', modalType, loader, injector, renderer, elementRef);
+
+ var m = new Modal(modalType, loader, injector, renderer, elementRef);
+
+ var modalPromise = new Promise(resolve => {
+
+ // Inject it into the page
+ m._inject().then(() => {
+ resolve(m);
+ })
+ })
+
+ return modalPromise;
}
- show() {
+ _inject() {
console.log('Modal show');
- return this.componentLoader.loadIntoNewLocation(Modal, this.elementRef).then((containerRef) => {
+
+ // Create the dialogRef here so that it can be injected into the content component.
+ var modalRef = new ModalRef();
+ var modalRefBinding = bind(ModalRef).toValue(modalRef);
+ var contentInjector = this.injector.resolveAndCreateChild([modalRefBinding]);
+
+ // Load the modal wrapper object and insert into the page
+ return this.componentLoader.loadIntoNewLocation(ModalContainer, this.elementRef).then((containerRef) => {
var modalEl = this.domRenderer.getHostElement(containerRef.hostView.render);
document.body.appendChild(modalEl);
- raf(() => {
- modalEl.classList.add('active');
- });
+ this.modalElement = modalEl;
- console.log('Loaded into new location', containerRef, modalEl);
+ console.log('Loaded into new location', modalEl);
+
+ modalRef.containerRef = containerRef;
+
+ // Now load the user's modal component into the Modal
+ return this.componentLoader.loadNextToExistingLocation(
+ this.modalType, containerRef.instance.contentRef, contentInjector).then(contentRef => {
+
+ modalRef.contentRef = contentRef;
+ modalRef.instance.modalRef = modalRef;
+ return modalRef;
+
+
+ // Wrap both component refs for the container and the content so that we can return
+ // the `instance` of the content but the dispose method of the container back to the
+ // opener.
+ //dialogRef.contentRef = contentRef;
+ //containerRef.instance.dialogRef = dialogRef;
+
+ //backdropRefPromise.then(backdropRef => {
+ // dialogRef.whenClosed.then((_) => {
+ // backdropRef.dispose();
+ // });
+ //});
+
+ //return dialogRef;
+ });
+ });
+ //});
+ }
+
+ show() {
+ raf(() => {
+ this.modalElement.classList.add('active');
});
}
- static show(loader: ComponentLoader, renderer: DomRenderer, elementRef: ElementRef) {
+
+ static show(modalType: Type, loader: ComponentLoader, injector: Injector, renderer: DomRenderer, elementRef: ElementRef) {
console.log('Showing modal');
- var newModal = new Modal(loader, renderer, elementRef);
- newModal.show();
- return newModal;
+ Modal.create(modalType, loader, injector, renderer, elementRef).then((newModal) => {
+ newModal.show();
+ });
}
}
-@Component({selector: 'ion-view'})
-@View({
- template: `
- First Page Header: {{ val }}
-
-
-
- First Page: {{ val }}
-
-
-
-
-
-
-
-
-
- `,
- directives: [NavbarTemplate, Navbar, Content]
+/**
+ * Container for user-provided dialog content.
+ */
+@Component({
+ selector: 'ion-modal'
})
-export class ModalFirstPage {
- constructor(
- nav: NavController
- ) {
- this.nav = nav;
- this.val = Math.round(Math.random() * 8999) + 1000;
- }
-
- push() {
- this.nav.push(ModalSecondPage, { id: 8675309, myData: [1,2,3,4] }, { animation: 'ios' });
- }
-}
-
-@Component({selector: 'ion-view'})
@View({
- template: `
- Second Page Header
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `,
- directives: [NavbarTemplate, Navbar, Content]
+ template: '
',
+ directives: [ModalContent]
})
-export class ModalSecondPage {
- constructor(
- nav: NavController,
- params: NavParams
- ) {
- this.nav = nav;
- this.params = params;
-
- console.log('Second page params:', params);
+class ModalContainer {
+ constructor() {
+ }
+}
+
+/**
+ * Simple decorator used only to communicate an ElementRef to the parent MdDialogContainer as the location
+ * for where the dialog content will be loaded.
+ */
+@Directive({selector: 'ion-modal-content'})
+class ModalContent {
+ constructor(@Parent() modalContainer: ModalContainer, elementRef: ElementRef) {
+ modalContainer.contentRef = elementRef;
+ }
+}
+
+
+
+export class ModalRef {
+ constructor() {
+ this._contentRef = null;
+ this.containerRef = null;
+ this.isClosed = false;
+ }
+
+ close() {
+ this.isClosed = true;
+ this.containerRef.dispose();
+ }
+
+
+ set contentRef(value: ComponentRef) {
+ this._contentRef = value;
+ }
+
+ /** Gets the component instance for the content of the dialog. */
+ get instance() {
+ if (isPresent(this._contentRef)) {
+ return this._contentRef.instance;
+ }
+
+ // The only time one could attempt to access this property before the value is set is if an access occurs during
+ // the constructor of the very instance they are trying to get (which is much more easily accessed as `this`).
+ throw "Cannot access dialog component instance *from* that component's constructor.";
}
-
- pop() {
- this.nav.pop();
- }
-
- push() {
- }
-
}
diff --git a/ionic/components/modal/test/basic/index.js b/ionic/components/modal/test/basic/index.js
index 28bc0a4e1d..ae8c14540d 100644
--- a/ionic/components/modal/test/basic/index.js
+++ b/ionic/components/modal/test/basic/index.js
@@ -1,9 +1,14 @@
import {DynamicComponentLoader, ElementRef, ComponentRef, onDestroy, DomRenderer} from 'angular2/angular2';
+import {bind, Injector} from 'angular2/di';
import {bootstrap} from 'angular2/angular2'
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
+import {Parent, Ancestor} from 'angular2/src/core/annotations_impl/visibility';
-import {Content, List, Item, Button, Modal} from 'ionic/ionic';
+import {Content, List, Item, Button, Modal, ModalRef} from 'ionic/ionic';
+
+import {Nav} from 'ionic/ionic';
+import {NavController, NavParams, NavbarTemplate, Navbar} from 'ionic/ionic';
@Component({ selector: 'ion-app' })
@@ -12,20 +17,124 @@ import {Content, List, Item, Button, Modal} from 'ionic/ionic';
directives: [Content, List, Item, Button]
})
class IonicApp {
- constructor(loader: DynamicComponentLoader, domRenderer: DomRenderer, elementRef: ElementRef) {
+ constructor(loader: DynamicComponentLoader, injector: Injector, domRenderer: DomRenderer, elementRef: ElementRef) {
this.loader = loader;
this.domRenderer = domRenderer;
this.elementRef = elementRef;
+ this.injector = injector;
console.log('IonicApp Start', loader, domRenderer, elementRef);
}
openModal() {
console.log('Opening modal');
- Modal.show(this.loader, this.domRenderer, this.elementRef);
+ Modal.show(ContactModal, this.loader, this.injector, this.domRenderer, this.elementRef);
}
}
+@Component({
+ selector: 'contact-modal'
+})
+@View({
+ template: '',
+ directives: [Nav]
+})
+export class ContactModal {
+ constructor(modalRef: ModalRef) {
+ this.initial = ModalFirstPage;
+ this.modalRef = modalRef;
+ }
+ close() {
+ console.log('Closing modal');
+ this.modalRef.close();
+ }
+}
+
+@Component({selector: 'ion-view'})
+@View({
+ template: `
+ First Page Header: {{ val }}
+
+
+
+
+
+
+
+ First Page: {{ val }}
+
+
+
+
+
+
+
+
+
+ `,
+ directives: [NavbarTemplate, Navbar, Content]
+})
+export class ModalFirstPage {
+ constructor(
+ @Parent() modal: ContactModal,
+ nav: NavController
+ ) {
+ this.modal = modal;
+ this.nav = nav;
+ this.val = Math.round(Math.random() * 8999) + 1000;
+ }
+
+ push() {
+ this.nav.push(ModalSecondPage, { id: 8675309, myData: [1,2,3,4] }, { animation: 'ios' });
+ }
+
+ closeModal() {
+ this.modal.close();
+ }
+}
+
+@Component({selector: 'ion-view'})
+@View({
+ template: `
+ Second Page Header
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ directives: [NavbarTemplate, Navbar, Content]
+})
+export class ModalSecondPage {
+ constructor(
+ nav: NavController,
+ params: NavParams
+ ) {
+ this.nav = nav;
+ this.params = params;
+
+ console.log('Second page params:', params);
+ }
+
+ pop() {
+ this.nav.pop();
+ }
+
+ push() {
+ }
+
+}
+
export function main() {
bootstrap(IonicApp).then((appRef) => {