diff --git a/ionic/components/action-sheet/action-sheet.ts b/ionic/components/action-sheet/action-sheet.ts index 7a12797c98..d2709f24dc 100644 --- a/ionic/components/action-sheet/action-sheet.ts +++ b/ionic/components/action-sheet/action-sheet.ts @@ -1,33 +1,79 @@ -import {Component, Injectable, Renderer} from 'angular2/core'; +import {Component, Renderer} from 'angular2/core'; import {NgFor, NgIf} from 'angular2/common'; +import {NavParams} from '../nav/nav-controller'; +import {ViewController} from '../nav/view-controller'; import {Config} from '../../config/config'; import {Icon} from '../icon/icon'; import {Animation} from '../../animations/animation'; -import {NavParams} from '../nav/nav-controller'; -import {extend} from '../../util/util'; + + +/** + * @name ActionSheet + * @description + * The Action Sheet is a slide-up dialog that lets the user choose from a set + * of options. Dangerous options are made obvious. There are easy ways to + * cancel out of the action sheet, such as tapping the backdrop or even hitting + * escape key on desktop. + * + * @usage + * ```ts + * ``` + * + * @demo /docs/v2/demos/action-sheet/ + * @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs} + */ + export class ActionSheet extends ViewController { + + constructor(data={}) { + data.buttons = data.buttons || []; + + super(ActionSheetCmp, data); + this.viewType = 'action-sheet'; + } + + getTransitionName(direction) { + let key = 'actionSheet' + (direction === 'back' ? 'Leave' : 'Enter'); + return this._nav && this._nav.config.get(key); + } + + setTitle(title) { + this._data.title = title; + } + + setSubTitle(subTitle) { + this._data.subTitle = subTitle; + } + + addButton(button) { + this._data.buttons.push(button); + } + + static create(data={}) { + return new ActionSheet(data); + } + + } + @Component({ selector: 'ion-action-sheet', template: - '
' + + '' + '
' + '
' + '
' + - '
{{d.titleText}}
' + - '' + - '' + '
' + - '
' + - '' + '
' + '
' + @@ -39,7 +85,10 @@ import {extend} from '../../util/util'; }) class ActionSheetCmp { - constructor(params: NavParams, renderer: Renderer) { + constructor( + private _viewCtrl: ViewController, + params: NavParams, renderer: Renderer + ) { this.d = params.data; if (this.d.cssClass) { @@ -47,121 +96,64 @@ class ActionSheetCmp { } } - cancel() { - this.d.cancel && this.d.cancel(); - return this.close(); - } + click(button) { + let shouldDismiss = true; - destructive() { - if (this.d.destructiveButtonClicked()) { - return this.close(); + if (button.handler) { + // a handler has been provided, execute it + if (button.handler() === false) { + // if the return value of the handler is false then do not dismiss + shouldDismiss = false; + } + } + + if (shouldDismiss) { + this.dismiss(); } } - buttonClicked(index) { - if (this.d.buttonClicked(index)) { - return this.close(); - } + dismiss() { + this._viewCtrl.dismiss(this); + } + + onPageLoaded() { + // normalize the data + let buttons = []; + + this.d.buttons.forEach(button => { + if (typeof button === 'string') { + button = { text: button }; + } + + if (button.style === 'cancel') { + this.d.cancelButton = button; + + } else { + if (button.style === 'destructive') { + button.cssClass = (button.cssClass + ' ' || '') + 'action-sheet-destructive'; + } + buttons.push(button); + } + }); + + this.d.buttons = buttons; + + let self = this; + self.keyUp = function(ev) { + if (ev.keyCode === 27) { + console.debug('actionsheet escape'); + self.dismiss(); + } + }; + + document.addEventListener('keyup', this.keyUp); + } + + onPageDidLeave() { + document.removeEventListener('keyup', this.keyUp); } } -/** - * @name ActionSheet - * @description - * The Action Sheet is a slide-up pane that lets the user choose from a set of options. Dangerous options are made obvious. - * There are easy ways to cancel out of the action sheet, such as tapping the backdrop or even hitting escape on the keyboard for desktop testing. - * - * @usage - * ```ts - * openMenu() { - * - * this.actionSheet.open({ - * buttons: [ - * { text: 'Share This' }, - * { text: 'Move' } - * ], - * destructiveText: 'Delete', - * titleText: 'Modify your album', - * cancelText: 'Cancel', - * cancel: function() { - * console.log('Canceled'); - * }, - * destructiveButtonClicked: () => { - * console.log('Destructive clicked'); - * }, - * buttonClicked: function(index) { - * console.log('Button clicked', index); - * if(index == 1) { return false; } - * return true; - * } - * - * }).then(actionSheetRef => { - * this.actionSheetRef = actionSheetRef; - * }); - * - * } - * ``` - * - * @demo /docs/v2/demos/action-sheet/ - * @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs} - */ -@Injectable() -export class ActionSheet { - - constructor(config: Config) { - //this.ctrl = ctrl; - this.config = config; - } - - /** - * Create and open a new Action Sheet. This is the - * public API, and most often you will only use ActionSheet.open() - * - * @param {Object} [opts={}] An object containing optional settings. - * - `[Object]` `buttons` Which buttons to show. Each button is an object with a `text` field. - * - `{string}` `titleText` The title to show on the action sheet. - * - `{string=}` `cancelText` the text for a 'cancel' button on the action sheet. - * - `{string=}` `destructiveText` The text for a 'danger' on the action sheet. - * - `{function=}` `cancel` Called if the cancel button is pressed, the backdrop is tapped or - * the hardware back button is pressed. - * - `{function=}` `buttonClicked` Called when one of the non-destructive buttons is clicked, - * with the index of the button that was clicked and the button object. Return true to close - * the action sheet, or false to keep it opened. - * - `{function=}` `destructiveButtonClicked` Called when the destructive button is clicked. - * Return true to close the action sheet, or false to keep it opened. - * - `{String}` `enterAnimation` The class used to animate an actionSheet that is entering. - * - `{String}` `leaveAnimation` The class used to animate an actionSheet that is leaving. - * @return {Promise} Promise that resolves when the action sheet is open. - */ - open(opts={}) { - opts = extend({ - pageType: OVERLAY_TYPE, - enterAnimation: this.config.get('actionSheetEnter'), - leaveAnimation: this.config.get('actionSheetLeave'), - cancelIcon: this.config.get('actionSheetCancelIcon'), - destructiveIcon: this.config.get('actionSheetDestructiveIcon') - }, opts); - - return this.ctrl.open(ActionSheetCmp, opts, opts); - } - - /** - * Retrieves an actionSheet instance. - * - * @param {String} [handle] The handle used to open the instance to be retrieved. - * @returns {ActionSheet} An actionSheet instance. - */ - get(handle) { - if (handle) { - return this.ctrl.getByHandle(handle); - } - return this.ctrl.getByType(OVERLAY_TYPE); - } - -} - -const OVERLAY_TYPE = 'action-sheet'; - class ActionSheetSlideIn extends Animation { diff --git a/ionic/components/action-sheet/test/basic/index.ts b/ionic/components/action-sheet/test/basic/index.ts index 0de8f0c928..ccebdce40a 100644 --- a/ionic/components/action-sheet/test/basic/index.ts +++ b/ionic/components/action-sheet/test/basic/index.ts @@ -1,41 +1,66 @@ -import {App, ActionSheet} from 'ionic/ionic'; +import {App, Page, ActionSheet, NavController} from 'ionic/ionic'; -@App({ +@Page({ templateUrl: 'main.html' }) -class E2EApp { +class E2EPage { - constructor(actionSheet: ActionSheet) { - this.actionSheet = actionSheet; + constructor(nav: NavController) { + this.nav = nav; } - openActionSheet() { + openActionSheet(ev) { + this.result = ''; - this.actionSheet.open({ + let actionSheet = ActionSheet.create({ buttons: [ - { text: 'Share This' }, - { text: 'Move' } - ], - destructiveText: 'Delete', - titleText: 'Modify your album', - cancelText: 'Cancel', - cancel: function() { - console.log('Canceled'); - }, - destructiveButtonClicked: () => { - console.log('Destructive clicked'); - }, - buttonClicked: function(index) { - console.log('Button clicked', index); - if(index == 1) { return false; } - return true; - } + { + text: 'Cancel', + style: 'cancel', // will always sort to be on the bottom + handler: () => { + console.log('cancel this clicked'); + this.result = 'Canceled'; + } + }, + { + text: 'Archive', + handler: () => { + console.log('Archive clicked'); + this.result = 'Archived'; + } + }, + { + text: 'No close', + handler: () => { + console.log('do not close clicked'); - }).then(actionSheetRef => { - this.actionSheetRef = actionSheetRef; + // returning false does not allow the actionsheet to be closed + return false; + } + }, + { + text: 'Destructive', + style: 'destructive', + handler: () => { + console.log('Destructive clicked'); + this.result = 'Destructive'; + } + } + ] }); + this.nav.present(actionSheet); } } + + +@App({ + template: '' +}) +class E2EApp { + constructor() { + this.root = E2EPage; + } +} diff --git a/ionic/components/action-sheet/test/basic/main.html b/ionic/components/action-sheet/test/basic/main.html index 7658c8dfe6..db7de5ed05 100644 --- a/ionic/components/action-sheet/test/basic/main.html +++ b/ionic/components/action-sheet/test/basic/main.html @@ -1,4 +1,12 @@ + + Action Sheet + + + +
+    Result: {{result}}
+  
diff --git a/ionic/components/alert/alert.ts b/ionic/components/alert/alert.ts index db2164d6b8..e124a4ce5a 100644 --- a/ionic/components/alert/alert.ts +++ b/ionic/components/alert/alert.ts @@ -1,57 +1,50 @@ import {Component, ElementRef, Renderer} from 'angular2/core'; import {NgClass, NgIf, NgFor, FORM_DIRECTIVES} from 'angular2/common'; -import {NavController, NavParams} from '../nav/nav-controller'; +import {NavParams} from '../nav/nav-controller'; import {ViewController} from '../nav/view-controller'; import {Animation} from '../../animations/animation'; import {Button} from '../button/button'; -import {extend, isDefined} from '../../util/util'; +import {isDefined} from '../../util/util'; export class Alert extends ViewController { - constructor(opts={}) { - super(AlertCmp, opts); + constructor(data={}) { + data.inputs = data.inputs || []; + data.buttons = data.buttons || []; - this.data.inputs = this.data.inputs || []; - this.data.buttons = this.data.buttons || []; + super(AlertCmp, data); + this.viewType = 'alert'; } getTransitionName(direction) { let key = (direction === 'back' ? 'alertLeave' : 'alertEnter'); - return this._nav.config.get(key); + return this._nav && this._nav.config.get(key); } setTitle(title) { - this.data.title = title; + this._data.title = title; } setSubTitle(subTitle) { - this.data.subTitle = subTitle; + this._data.subTitle = subTitle; } setBody(body) { - this.data.body = body; + this._data.body = body; } addInput(input) { - this.data.inputs.push(input); + this._data.inputs.push(input); } addButton(button) { - this.data.buttons.push(button); + this._data.buttons.push(button); } - onDismiss(handler) { - this.data.onDismiss = handler; - } - - dismiss() { - this._nav.dismiss(this); - } - - static create(opts={}) { - return new Alert(opts); + static create(data={}) { + return new Alert(data); } } @@ -102,9 +95,10 @@ class AlertCmp { let shouldDismiss = true; if (button.handler) { - // a handler has been provided, run it + // a handler has been provided, execute it + // pass the handler the values from the inputs if (button.handler(this.getValues()) === false) { - // if the return value is a false then do not close + // if the return value of the handler is false then do not dismiss shouldDismiss = false; } } @@ -126,7 +120,7 @@ class AlertCmp { return values; } - onPageWillEnter() { + onPageLoaded() { // normalize the data this.d.buttons = this.d.buttons.map(button => { if (typeof button === 'string') { @@ -137,9 +131,9 @@ class AlertCmp { this.d.inputs = this.d.inputs.map((input, index) => { return { - name: input.name || index, + name: isDefined(input.name) ? input.name : index, label: input.label, - placeholder: input.placeholder || '', + placeholder: isDefined(input.placeholder) ? input.placeholder : '', type: input.type || 'text', value: isDefined(input.value) ? input.value : '' } @@ -173,7 +167,6 @@ class AlertCmp { } onPageDidLeave() { - this.d.onDismiss && this.d.onDismiss(this.getValues()); document.removeEventListener('keyup', this.keyUp); } } diff --git a/ionic/components/alert/test/basic/index.ts b/ionic/components/alert/test/basic/index.ts index adccde6271..1a6a3aecf8 100644 --- a/ionic/components/alert/test/basic/index.ts +++ b/ionic/components/alert/test/basic/index.ts @@ -8,7 +8,6 @@ class E2EPage { constructor(nav: NavController) { this.nav = nav; - this.testAlertOpen = false; this.testConfirmOpen = false; this.testPromptOpen = false; this.testConfirmResult = ''; @@ -19,15 +18,10 @@ class E2EPage { let alert = Alert.create({ title: 'Alert!', subTitle: 'Subtitle!!!', - buttons: ['Ok'], - onDismiss: () => { - this.testAlertOpen = false; - } + buttons: ['Ok'] }); this.nav.present(alert); - - this.testAlertOpen = true; } doConfirm() { @@ -39,6 +33,7 @@ class E2EPage { handler: () => { console.log('Confirm Cancel'); this.testConfirmResult = 'Cancel'; + this.testConfirmOpen = false; } }); alert.addButton({ @@ -46,13 +41,10 @@ class E2EPage { handler: () => { console.log('Confirm Ok'); this.testConfirmResult = 'Ok'; + this.testConfirmOpen = false; } }); - alert.onDismiss(data => { - this.testConfirmOpen = false; - }); - this.nav.present(alert).then(() => { this.testConfirmOpen = true; }); @@ -87,14 +79,11 @@ class E2EPage { text: 'Ok', handler: data => { console.log('Prompt data:', data); + this.testPromptOpen = false; + this.testPromptResult = data; } }); - alert.onDismiss(data => { - this.testPromptOpen = false; - this.testPromptResult = data; - }); - this.nav.present(alert).then(() => { this.testPromptOpen = true; }); diff --git a/ionic/components/alert/test/basic/main.html b/ionic/components/alert/test/basic/main.html index a5924ef37a..14b8b911cb 100644 --- a/ionic/components/alert/test/basic/main.html +++ b/ionic/components/alert/test/basic/main.html @@ -10,7 +10,6 @@
-    Alert Opened: {{testAlertOpen}}
     Confirm Opened: {{testConfirmOpen}}
     Confirm Result: {{testConfirmResult}}
     Prompt Opened: {{testPromptOpen}}
diff --git a/ionic/components/modal/modal.ts b/ionic/components/modal/modal.ts
index 6da84092ed..a45b19a07a 100644
--- a/ionic/components/modal/modal.ts
+++ b/ionic/components/modal/modal.ts
@@ -1,35 +1,53 @@
-import {Injectable, Type} from 'angular2/core';
-
+import {NavController, NavParams} from '../nav/nav-controller';
+import {ViewController} from '../nav/view-controller';
 import {Config} from '../../config/config';
 import {Animation} from '../../animations/animation';
-import {extend} from '../../util';
 
 /**
  * @name Modal
  * @description
  * The Modal is a content pane that can go over the user's current page.
- * Usually used for making a choice or editing an item. A modal can be opened
- * similar to how {@link /docs/v2/api/components/nav/NavController/#push NavController.push}  works,
- * where it is passed a Page component, along with optional Page params,
- * and options for presenting the modal.
+ * Usually it is used for making a choice or editing an item. A modal uses the
+ * `NavController` to "present" itself in the root nav stack. It is added to the
+ * stack similar to how
+ * {@link /docs/v2/api/components/nav/NavController/#push NavController.push}
+ * works, where it is passed a Page component, along with optional Page params
+ *
+ * When a modal (or any other overlay such as an alert or actionsheet) is
+ * "presented" to a nav controller, the overlay is added to the app's root nav.
+ * After the modal has been presented, from within the component instance The
+ * modal can later be closed or "dimsissed" by using the ViewController's
+ * `dismiss` method. Additinoally, you can dismiss any overlay by using `pop`
+ * on the root nav controller.
+ *
+ * A modal can also emit data, which is useful when it is used to add or edit
+ * data. For example, a profile page could slide up in a modal, and on submit,
+ * the submit button could emit the updated profile data, then dismiss the modal.
+ * From that point, anything which is subscribed to the modal's `data` event
+ * would receive the modal's data.
  *
  * @usage
  * ```ts
+ * import {Modal, NavController} from 'ionic/ionic';
+ *
  * class MyApp {
  *
- *  constructor(modal: Modal) {
- *    this.modal = modal;
+ *  constructor(nav: NavController) {
+ *    this.nav = nav;
  *  }
  *
- *  openContactModal() {
- *    this.modal.open(ContactUs);
+ *  presentContactModal() {
+ *    let contactModal = Modal.create(ContactUs);
+ *    this.nav.present(contactModal);
  *  }
  *
- *  openProfileModal() {
- *    this.modal.open(Profile, { userId: 8675309 }, {
- *      enterAnimation: 'my-fade-in',
- *      leaveAnimation: 'my-fade-out',
- *      handle: 'profile-modal'
+ *  presentProfileModal() {
+ *    let profileModal = Modal.create(Profile, { userId: 8675309 });
+ *    this.nav.present(profileModal, {
+ *      animation: 'my-fade-in'
+ *    });
+ *    profileModal.data.subscribe(data => {
+ *      console.log(data);
  *    });
  *  }
  *
@@ -38,64 +56,24 @@ import {extend} from '../../util';
  * @demo /docs/v2/demos/modal/
  * @see {@link /docs/v2/components#modals Modal Component Docs}
  */
-@Injectable()
-export class Modal {
+export class Modal extends ViewController {
 
-  constructor(config: Config) {
-    //this.ctrl = ctrl;
-    this.config = config;
+  constructor(componentType, data={}) {
+    super(componentType, data);
+    this.viewType = 'modal';
   }
 
-  /**
-   * Opens a new modal using the page component is was pass as the first
-   * argument. This is similar to how NavController's `push` method works.
-   * Currently you must have `` in the `@App` component's template
-   * for the modal to work correctly. (This is something that will
-   * be hopefully be removed in the near future.)
-   *
-   * @param pageComponent  The Page component to load in the modal.
-   * @param {Object} [params={}]  Optional data which can be passed to the page
-   * component, which can be read from the constructor's `NavParams`.
-   * @param {Object} [opts={}]  Additional options for this one modal instance of.
-   * Options include `enterAnimation` and `leaveAnimation`, which
-   * allows customization of which animation to use.
-   * @returns {Promise} Returns a promise which resolves when the modal has
-   * loaded and its entering animation has completed. The resolved promise's
-   * value is the instance of the newly created modal.
-   */
-  open(pageComponent: Type, params={}, opts={}) {
-    opts = extend({
-      pageType: OVERLAY_TYPE,
-      enterAnimation: this.config.get('modalEnter'),
-      leaveAnimation: this.config.get('modalLeave'),
-    }, opts);
-
-    return this.ctrl.open(pageComponent, params, opts);
+  getTransitionName(direction) {
+    let key = (direction === 'back' ? 'modalLeave' : 'modalEnter');
+    return this._nav && this._nav.config.get(key);
   }
 
-  /**
-   * Get the instance of a modal. This is usually helpful to getting ahold of a
-   * certain modal, from anywhere within the app, and closing it. By calling
-   * just `get()` without a `handle` argument, it'll return the active modal
-   * on top (it is possible to have multipe modals opened at the same time).
-   * If getting just the active modal isn't enough, when creating
-   * a modal, it's options can be given a `handle`, which is simply a string-based
-   * name for the modal instance. You can later get a reference to that modal's
-   * instance by calling this method with the same handle name.
-   * @param  [handle]  Optional string name given in the modal's options when it was opened.
-   * @returns Returns the instance of the modal if it is found, otherwise `null`.
-   */
-  get(handle) {
-    if (handle) {
-      return this.ctrl.getByHandle(handle);
-    }
-    return this.ctrl.getByType(OVERLAY_TYPE);
+  static create(componentType, data={}) {
+    return new Modal(componentType, data);
   }
 
 }
 
-const OVERLAY_TYPE = 'modal';
-
 
 /**
  * Animations for modals
@@ -108,6 +86,13 @@ class ModalSlideIn extends Animation {
       .duration(400)
       .fromTo('translateY', '100%', '0%')
       .before.addClass('show-page');
+
+    if (enteringView.hasNavbar()) {
+      // entering page has a navbar
+      let enteringNavBar = new Animation(enteringView.navbarRef());
+      enteringNavBar.before.addClass('show-navbar');
+      this.add(enteringNavBar);
+    }
   }
 }
 Animation.register('modal-slide-in', ModalSlideIn);
@@ -134,6 +119,13 @@ class ModalMDSlideIn extends Animation {
       .fromTo('translateY', '40px', '0px')
       .fadeIn()
       .before.addClass('show-page');
+
+    if (enteringView.hasNavbar()) {
+      // entering page has a navbar
+      let enteringNavBar = new Animation(enteringView.navbarRef());
+      enteringNavBar.before.addClass('show-navbar');
+      this.add(enteringNavBar);
+    }
   }
 }
 Animation.register('modal-md-slide-in', ModalMDSlideIn);
diff --git a/ionic/components/modal/test/basic/index.ts b/ionic/components/modal/test/basic/index.ts
index 0fdab060a2..6140dba8df 100644
--- a/ionic/components/modal/test/basic/index.ts
+++ b/ionic/components/modal/test/basic/index.ts
@@ -1,15 +1,14 @@
 import {App, Page, Config, Platform} from 'ionic/ionic';
-import {Modal, ActionSheet, NavController, NavParams, Animation} from 'ionic/ionic';
+import {Modal, ActionSheet, NavController, NavParams, Animation, ViewController} from 'ionic/ionic';
 
 
-@App({
+@Page({
   templateUrl: 'main.html'
 })
-class E2EApp {
-
-  constructor(modal: Modal, config: Config, platform: Platform) {
-    this.modal = modal;
+class E2EPage {
 
+  constructor(nav: NavController, config: Config, platform: Platform) {
+    this.nav = nav;
     console.log('platforms', platform.platforms());
     console.log('mode', config.get('mode'));
 
@@ -29,32 +28,29 @@ class E2EApp {
     });
   }
 
-  openModal() {
-    this.modal.open(ModalPassParams, { userId: 3141209 });
-  }
+  presentModal() {
+    let modal = Modal.create(ModalPassData, { userId: 8675309 });
+    this.nav.present(modal);
 
-  openToolbarModal() {
-    this.modal.open(ToolbarModal).then(modalRef => {
-      // modal has finished opening
-      // modalRef is a reference to the modal instance
-      modalRef.onClose = (modalData) => {
-        // somehow modalRef.close(modalData) was called w/ modalData
-        console.log('modalRef.onClose', modalData)
-      }
+    modal.data.subscribe(data => {
+      console.log('data', data);
     });
   }
 
-  openModalChildNav() {
-    this.modal.open(ContactUs, null, {
-      handle: 'my-awesome-modal'
-    });
+  presentModalChildNav() {
+    let modal = Modal.create(ContactUs);
+    this.nav.present(modal);
   }
 
-  openModalCustomAnimation() {
-    this.modal.open(ContactUs, null, {
-      handle: 'my-awesome-modal',
-      enterAnimation: 'my-fade-in',
-      leaveAnimation: 'my-fade-out'
+  presentToolbarModal() {
+    let modal = Modal.create(ToolbarModal);
+    this.nav.present(modal);
+  }
+
+  presentModalCustomAnimation() {
+    let modal = Modal.create(ContactUs);
+    this.nav.present(modal, {
+      animation: 'my-fade-in'
     });
   }
 }
@@ -62,44 +58,65 @@ class E2EApp {
 
 @Page({
   template: `
-    

Pass Params

-

User Id: {{userId}}

-

+ + Data in/out + + + + + UserId + + + + Name + + + + + ` }) -class ModalPassParams { - constructor(private modal: Modal, params: NavParams) { - this.userId = params.get('userId'); +class ModalPassData { + constructor(params: NavParams, viewCtrl: ViewController) { + this.data = { + userId: params.get('userId'), + name: 'Jenny' + }; + this.viewCtrl = viewCtrl; + } + + submit() { + this.viewCtrl.data.emit(this.data); + this.viewCtrl.dismiss(); } } @Page({ template: ` - - Modals + + Toolbar 1 - - Another toolbar + + Toolbar 2 - ` }) class ToolbarModal { - constructor(private modal: Modal) {} - closeModal() { - this.close({ - adel: 'hello', - lionel: 'hello' - }); + constructor(viewCtrl: ViewController) { + this.viewCtrl = viewCtrl; + } + + dismiss() { + this.viewCtrl.dismiss(); } } @@ -142,7 +159,7 @@ class ContactUs { First Page Header - + @@ -152,23 +169,14 @@ class ContactUs {

-

- -

` }) class ModalFirstPage { - constructor( - nav: NavController, - modal: Modal, - actionSheet: ActionSheet - ) { + constructor(nav: NavController) { this.nav = nav; - this.modal = modal; - this.actionSheet = actionSheet; } push() { @@ -179,12 +187,8 @@ class ModalFirstPage { this.nav.push(page, params, opts); } - closeModal() { - this.modal.get().close(); - } - - closeByHandeModal() { - this.modal.get('my-awesome-modal').close(); + dismiss() { + this.nav.rootNav.pop(); } openActionSheet() { @@ -239,6 +243,16 @@ class ModalSecondPage { } +@App({ + template: '' +}) +class E2EApp { + constructor() { + this.root = E2EPage; + } +} + + class FadeIn extends Animation { constructor(enteringView, leavingView) { super(enteringView.pageRef()); diff --git a/ionic/components/modal/test/basic/main.html b/ionic/components/modal/test/basic/main.html index 2ae592b345..8689ed0d35 100644 --- a/ionic/components/modal/test/basic/main.html +++ b/ionic/components/modal/test/basic/main.html @@ -1,15 +1,19 @@ + + Modals + +

- +

- +

- +

- +

diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts index 78adc71d51..c810591a75 100644 --- a/ionic/components/nav/nav-controller.ts +++ b/ionic/components/nav/nav-controller.ts @@ -268,8 +268,6 @@ export class NavController extends Ion { // create a new ViewController let enteringView = new ViewController(componentType, params); enteringView.setNav(this); - enteringView.pageType = opts.pageType; - enteringView.handle = opts.handle || null; // default the direction to "forward" opts.direction = opts.direction || 'forward'; @@ -293,7 +291,9 @@ export class NavController extends Ion { } present(enteringView, opts={}) { - enteringView.setNav(this); + let rootNav = this.rootNav; + + enteringView.setNav(rootNav); let resolve; let promise = new Promise(res => { resolve = res; }); @@ -303,19 +303,24 @@ export class NavController extends Ion { opts.direction = 'forward'; if (!opts.animation) { - opts.animation = enteringView.getTransitionName(opts.direction); + opts.animation = enteringView.getTransitionName('forward'); } + enteringView.setLeavingOpts({ + keyboardClose: false, + skipCache: true, + direction: 'back', + animation: enteringView.getTransitionName('back') + }); + // the active view is going to be the leaving one (if one exists) - let leavingView = this.getActive() || new ViewController(); + let leavingView = rootNav.getActive() || new ViewController(); leavingView.shouldCache = (isBoolean(opts.cacheLeavingView) ? opts.cacheLeavingView : true); leavingView.shouldDestroy = !leavingView.shouldCache; if (leavingView.shouldDestroy) { leavingView.willUnload(); } - let rootNav = this.rootNav; - // add the view to the stack rootNav._add(enteringView); @@ -325,20 +330,6 @@ export class NavController extends Ion { return promise; } - dismiss(leavingView, opts={}) { - opts.skipCache = true; - opts.direction ='back'; - - if (!opts.animation) { - opts.animation = leavingView.getTransitionName(opts.direction); - } - - let rootNav = this.rootNav; - - let index = rootNav.indexOf(leavingView); - return rootNav.remove(index, opts); - } - /** * If you wanted to navigate back from a current view, you can use the back-button or programatically call `pop()` * Similar to `push()`, you can pass animation options. @@ -528,7 +519,7 @@ export class NavController extends Ion { * @param {Object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise when the view has been removed */ - remove(index, opts = {}) { + remove(index, opts={}) { if (index < 0 || index >= this._views.length) { return Promise.reject("index out of range"); } @@ -854,6 +845,7 @@ export class NavController extends Ion { let transAnimation = Animation.createTransition(enteringView, leavingView, opts); + if (opts.animate === false) { // force it to not animate the elements, just apply the "to" styles transAnimation.clearDuration(); @@ -867,8 +859,8 @@ export class NavController extends Ion { this.app.setEnabled(enableApp, duration); this.setTransitioning(!enableApp, duration); - if (opts.pageType) { - transAnimation.before.addClass(opts.pageType); + if (enteringView.viewType) { + transAnimation.before.addClass(enteringView.viewType); } wtfEndTimeRange(wtfScope); @@ -1401,34 +1393,6 @@ export class NavController extends Ion { return null; } - /** - * @private - * @param {Handle} The handle of the page you want to get - * @returns {Component} Returns the component that matches the handle given - */ - getByHandle(handle) { - for (let i = 0, ii = this._views.length; i < ii; i++) { - if (this._views[i].handle === handle) { - return this._views[i]; - } - } - return null; - } - - /** - * @private - * @param {TODO} pageType TODO - * @returns {TODO} TODO - */ - getByType(pageType) { - for (let i = 0, ii = this._views.length; i < ii; i++) { - if (this._views[i].pageType === pageType) { - return this._views[i]; - } - } - return null; - } - /** * @private * @param {TODO} view TODO diff --git a/ionic/components/nav/view-controller.ts b/ionic/components/nav/view-controller.ts index a062acfe39..fee7c1019e 100644 --- a/ionic/components/nav/view-controller.ts +++ b/ionic/components/nav/view-controller.ts @@ -1,3 +1,4 @@ +import {Output, EventEmitter} from 'angular2/core'; import {NavParams} from './nav-controller'; /** @@ -16,16 +17,20 @@ import {NavParams} from './nav-controller'; * ``` */ export class ViewController { + @Output() data: EventEmitter = new EventEmitter(); constructor(componentType, data={}) { this.componentType = componentType; - this.data = data; + this._data = data; this.instance = {}; this.state = 0; this._destroys = []; this._loaded = false; + this._outputData = null; this.shouldDestroy = false; this.shouldCache = false; + this.viewType = ''; + this._leavingOpts = null; } setNav(navCtrl) { @@ -37,7 +42,15 @@ export class ViewController { } getNavParams() { - return new NavParams(this.data); + return new NavParams(this._data); + } + + dismiss() { + return this._nav.remove(this._nav.indexOf(this), this._leavingOpts); + } + + setLeavingOpts(opts) { + this._leavingOpts = opts; } /**