From a6585246af4c165a12e6254c358f8677ce98156a Mon Sep 17 00:00:00 2001 From: Dan Bucholtz Date: Wed, 18 May 2016 13:11:59 -0500 Subject: [PATCH] feat(modal): add inset modal feature * feat(inset-modal): add dynamic component loading functionality for inset modal * style(modal): moved border-radius to a variable, added an additional data binding activity in moved border-radius to a variable, added an additional data binding activity in an e2e test * refactor(modal): refactor sass and remove some unnecessary stuff * refactor(modal): migrate to Angular RC import syntax Closes #5423 --- ionic/components/modal/modal.ios.scss | 12 +++- ionic/components/modal/modal.md.scss | 2 +- ionic/components/modal/modal.scss | 55 ++++++++++++---- ionic/components/modal/modal.ts | 77 +++++++++++++++++++--- ionic/components/modal/modal.wp.scss | 2 +- ionic/components/modal/test/basic/index.ts | 35 +++++++++- 6 files changed, 153 insertions(+), 30 deletions(-) diff --git a/ionic/components/modal/modal.ios.scss b/ionic/components/modal/modal.ios.scss index 9bf6a6f6803..68e67f4aa46 100644 --- a/ionic/components/modal/modal.ios.scss +++ b/ionic/components/modal/modal.ios.scss @@ -4,8 +4,16 @@ // -------------------------------------------------- $modal-ios-background-color: $background-ios-color !default; +$modal-ios-border-radius: 5px !default; - -ion-page.modal { +.modal ion-page { background-color: $modal-ios-background-color; } + +.modal-wrapper { + @media only screen and (min-width: 768px) and (min-height: 600px) { + overflow: hidden; + + border-radius: $modal-ios-border-radius; + } +} diff --git a/ionic/components/modal/modal.md.scss b/ionic/components/modal/modal.md.scss index 614257d49bb..33fafdf095d 100644 --- a/ionic/components/modal/modal.md.scss +++ b/ionic/components/modal/modal.md.scss @@ -6,6 +6,6 @@ $modal-md-background-color: $background-md-color !default; -ion-page.modal { +.modal ion-page { background-color: $modal-md-background-color; } diff --git a/ionic/components/modal/modal.scss b/ionic/components/modal/modal.scss index 9784b3af22a..1a598f9fe0c 100644 --- a/ionic/components/modal/modal.scss +++ b/ionic/components/modal/modal.scss @@ -3,27 +3,54 @@ // Modals // -------------------------------------------------- -ion-page.modal { - z-index: $z-index-overlay; +$modal-inset-min-width: 768px !default; +$modal-inset-min-height-small: 600px !default; +$modal-inset-min-height-large: 768px !default; +$modal-inset-width: 600px !default; +$modal-inset-height-small: 500px !default; +$modal-inset-height-large: 600px !default; - // hidden by default to prevent flickers, the animation will show it - transform: translate3d(0, 100%, 0); +.modal { + position: absolute; + top: 0; + left: 0; - @media only screen and (min-width: 768px) and (min-height: 600px){ + display: block; + + width: 100%; + height: 100%; + + .backdrop { + @media not all and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) { + display: none; + } + } +} + +.modal-wrapper { + z-index: 10; + + height: 100%; + + @media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-small) { position: absolute; - top: calc(50% - 250px); - left: calc(50% - 300px); + top: calc(50% - (#{$modal-inset-height-small}/2)); + left: calc(50% - (#{$modal-inset-width}/2)); - width: 600px; - height: 500px; + width: $modal-inset-width; + height: $modal-inset-height-small; } - @media only screen and (min-width: 768px) and (min-height: 768px){ + @media only screen and (min-width: $modal-inset-min-width) and (min-height: $modal-inset-min-height-large) { position: absolute; - top: calc(50% - 300px); - left: calc(50% - 300px); + top: calc(50% - (#{$modal-inset-height-large}/2)); + left: calc(50% - (#{$modal-inset-width}/2)); - width: 600px; - height: 600px; + width: $modal-inset-width; + height: $modal-inset-height-large; } } + +.show-page ion-page { + display: flex; +} diff --git a/ionic/components/modal/modal.ts b/ionic/components/modal/modal.ts index 6d6a98f1e7c..69ec70f6567 100644 --- a/ionic/components/modal/modal.ts +++ b/ionic/components/modal/modal.ts @@ -1,3 +1,6 @@ +import {Component, DynamicComponentLoader, ViewChild, ViewContainerRef} from '@angular/core'; + +import {NavParams} from '../nav/nav-params'; import {ViewController} from '../nav/view-controller'; import {Animation} from '../../animations/animation'; import {Transition, TransitionOptions} from '../../transitions/transition'; @@ -103,8 +106,9 @@ import {Transition, TransitionOptions} from '../../transitions/transition'; */ export class Modal extends ViewController { - constructor(componentType, data = {}) { - super(componentType, data); + constructor(componentType, data: any = {}) { + data.componentToPresent = componentType; + super(ModalComponent, data); this.viewType = 'modal'; this.isOverlay = true; } @@ -127,6 +131,30 @@ export class Modal extends ViewController { } +@Component({ + selector: 'ion-modal', + template: ` +
+ + ` +}) +class ModalComponent { + + @ViewChild('wrapper', {read: ViewContainerRef}) wrapper: ViewContainerRef; + + constructor(private _loader: DynamicComponentLoader, private _navParams: NavParams, private _viewCtrl: ViewController) { + } + + ngAfterViewInit() { + let component = this._navParams.data.componentToPresent; + this._loader.loadNextToLocation(component, this.wrapper).then(componentInstance => { + this._viewCtrl.setInstance(componentInstance.instance); + // TODO - validate what life cycle events aren't call and possibly call them here if needed + }); + } +} /** * Animations for modals @@ -134,12 +162,19 @@ export class Modal extends ViewController { class ModalSlideIn extends Transition { constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) { super(opts); + + let ele = enteringView.pageRef().nativeElement; + let backdrop = new Animation(ele.querySelector('.backdrop')); + backdrop.fromTo('opacity', 0.01, 0.4); + let wrapper = new Animation(ele.querySelector('.modal-wrapper')); + wrapper.fromTo('translateY', '100%', '0%'); this .element(enteringView.pageRef()) .easing('cubic-bezier(0.36,0.66,0.04,1)') .duration(400) - .fromTo('translateY', '100%', '0%') - .before.addClass('show-page'); + .before.addClass('show-page') + .add(backdrop) + .add(wrapper); if (enteringView.hasNavbar()) { // entering page has a navbar @@ -155,11 +190,19 @@ Transition.register('modal-slide-in', ModalSlideIn); class ModalSlideOut extends Transition { constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) { super(opts); + + let ele = leavingView.pageRef().nativeElement; + let backdrop = new Animation(ele.querySelector('.backdrop')); + backdrop.fromTo('opacity', 0.4, 0.0); + let wrapper = new Animation(ele.querySelector('.modal-wrapper')); + wrapper.fromTo('translateY', '0%', '100%'); + this .element(leavingView.pageRef()) .easing('ease-out') .duration(250) - .fromTo('translateY', '0%', '100%'); + .add(backdrop) + .add(wrapper); } } Transition.register('modal-slide-out', ModalSlideOut); @@ -168,13 +211,21 @@ Transition.register('modal-slide-out', ModalSlideOut); class ModalMDSlideIn extends Transition { constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) { super(opts); + + let ele = enteringView.pageRef().nativeElement; + let backdrop = new Animation(ele.querySelector('.backdrop')); + backdrop.fromTo('opacity', 0.01, 0.4); + let wrapper = new Animation(ele.querySelector('.modal-wrapper')); + wrapper.fromTo('translateY', '40px', '0px'); + this .element(enteringView.pageRef()) .easing('cubic-bezier(0.36,0.66,0.04,1)') .duration(280) - .fromTo('translateY', '40px', '0px') .fadeIn() - .before.addClass('show-page'); + .before.addClass('show-page') + .add(backdrop) + .add(wrapper); if (enteringView.hasNavbar()) { // entering page has a navbar @@ -190,12 +241,20 @@ Transition.register('modal-md-slide-in', ModalMDSlideIn); class ModalMDSlideOut extends Transition { constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) { super(opts); + + let ele = leavingView.pageRef().nativeElement; + let backdrop = new Animation(ele.querySelector('.backdrop')); + backdrop.fromTo('opacity', 0.4, 0.0); + let wrapper = new Animation(ele.querySelector('.modal-wrapper')); + wrapper.fromTo('translateY', '0px', '40px'); + this .element(leavingView.pageRef()) .duration(200) .easing('cubic-bezier(0.47,0,0.745,0.715)') - .fromTo('translateY', '0px', '40px') - .fadeOut(); + .fadeOut() + .add(wrapper) + .add(backdrop); } } Transition.register('modal-md-slide-out', ModalMDSlideOut); diff --git a/ionic/components/modal/modal.wp.scss b/ionic/components/modal/modal.wp.scss index 8efb3cb9f2c..11f8daa08c0 100644 --- a/ionic/components/modal/modal.wp.scss +++ b/ionic/components/modal/modal.wp.scss @@ -6,6 +6,6 @@ $modal-wp-background-color: $background-wp-color !default; -ion-page.modal { +.modal ion-page { background-color: $modal-wp-background-color; } diff --git a/ionic/components/modal/test/basic/index.ts b/ionic/components/modal/test/basic/index.ts index 16703a992be..eeeaca1f565 100644 --- a/ionic/components/modal/test/basic/index.ts +++ b/ionic/components/modal/test/basic/index.ts @@ -1,6 +1,5 @@ import {App, Page, Config, Platform} from '../../../../../ionic'; -import {Modal, ActionSheet, NavController, NavParams, Transition, TransitionOptions, ViewController} from '../../../../../ionic';; - +import {Modal, ActionSheet, NavController, NavParams, Transition, TransitionOptions, ViewController} from '../../../../../ionic'; @Page({ templateUrl: 'main.html' @@ -105,6 +104,22 @@ class ModalPassData { submit() { this.viewCtrl.dismiss(this.data); } + + onPageWillEnter(){ + console.log("ModalPassData onPagewillEnter fired"); + } + + onPageDidEnter(){ + console.log("ModalPassData onPageDidEnter fired"); + } + + onPageWillLeave(){ + console.log("ModalPassData onPageWillLeave fired"); + } + + onPageDidLeave(){ + console.log("ModalPassData onPageDidLeave fired"); + } } @@ -242,11 +257,25 @@ class ContactUs {

+ + + Item Number: {{item.value}} + + ` }) class ModalFirstPage { - constructor(private nav: NavController) {} + + private items:any[]; + constructor(private nav: NavController) { + this.items = []; + for ( let i = 0; i < 50; i++ ){ + this.items.push({ + value: (i + 1) + }); + } + } push() { let page = ModalSecondPage;