From 79ba6391d699f2340a750257035c2d6edb2984a8 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Fri, 6 Apr 2018 16:19:32 +0200 Subject: [PATCH] fix(angular): change detection --- .../directives/navigation/ion-back-button.ts | 4 +- angular/src/directives/proxies.ts | 4 +- angular/src/providers/angular-delegate.ts | 86 +++++++++++-------- .../src/app/no-routing-nav/pages/page-one.ts | 10 +-- .../components/action-sheet/action-sheet.tsx | 4 +- core/src/components/alert/alert.tsx | 3 +- 6 files changed, 60 insertions(+), 51 deletions(-) diff --git a/angular/src/directives/navigation/ion-back-button.ts b/angular/src/directives/navigation/ion-back-button.ts index 43b3cce9f7..53e80d60ad 100644 --- a/angular/src/directives/navigation/ion-back-button.ts +++ b/angular/src/directives/navigation/ion-back-button.ts @@ -1,7 +1,7 @@ import { Directive, ElementRef, HostListener, Input, Optional } from '@angular/core'; -import { IonRouterOutlet } from './ion-router-outlet'; import { Router } from '@angular/router'; -import { NavController } from '../..'; +import { NavController } from '../../providers/nav-controller'; +import { IonRouterOutlet } from './ion-router-outlet'; @Directive({ selector: 'ion-back-button' diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts index 67eec2b84c..c33db615b3 100644 --- a/angular/src/directives/proxies.ts +++ b/angular/src/directives/proxies.ts @@ -2,7 +2,7 @@ import { Directive as NgDirective, ElementRef, EventEmitter as NgEventEmitter, Input as NgInput, Output as NgOutput } from '@angular/core'; -export function method(ref: ElementRef, methodName: string, ...args: any[]) { +export function method(ref: ElementRef, methodName: string, args: any[]) { return ref.nativeElement.componentOnReady() .then((el: any) => el[methodName].apply(el, args)); } @@ -907,8 +907,6 @@ export class Menu { @NgInput() maxEdgeStart: number; @NgOutput() ionOpen: NgEventEmitter; @NgOutput() ionClose: NgEventEmitter; - @NgOutput() ionMenuDidLoad: NgEventEmitter; - @NgOutput() ionMenuDidUnload: NgEventEmitter; @NgOutput() ionMenuChange: NgEventEmitter; isOpen(...__args: any[]): Promise { return method(this.r, isOpen, __args); diff --git a/angular/src/providers/angular-delegate.ts b/angular/src/providers/angular-delegate.ts index 0325f25bcc..6ef022bd2c 100644 --- a/angular/src/providers/angular-delegate.ts +++ b/angular/src/providers/angular-delegate.ts @@ -1,10 +1,4 @@ -import { - ApplicationRef, - ComponentFactoryResolver, - Injectable, - Injector, -} from '@angular/core'; - +import { ApplicationRef, ComponentFactoryResolver, Injectable, Injector, NgZone } from '@angular/core'; import { FrameworkDelegate, ViewLifecycle } from '@ionic/core'; @@ -12,11 +6,12 @@ import { FrameworkDelegate, ViewLifecycle } from '@ionic/core'; export class AngularDelegate { constructor( - private appRef: ApplicationRef + private appRef: ApplicationRef, + private zone: NgZone ) {} create(cfr: ComponentFactoryResolver, injector: Injector) { - return new AngularFrameworkDelegate(cfr, injector, this.appRef); + return new AngularFrameworkDelegate(cfr, injector, this.appRef, this.zone); } } @@ -28,40 +23,61 @@ export class AngularFrameworkDelegate implements FrameworkDelegate { constructor( private cfr: ComponentFactoryResolver, private injector: Injector, - private appRef: ApplicationRef + private appRef: ApplicationRef, + private zone: NgZone, ) {} - attachViewToDom(container: any, component: any, data?: any, cssClasses?: string[]): Promise { - - const componentFactory = this.cfr.resolveComponentFactory(component); - const hostElement = document.createElement(componentFactory.selector); - if (data) { - Object.assign(hostElement, data); - } - - const childInjector = Injector.create([], this.injector); - const componentRef = componentFactory.create(childInjector, [], hostElement); - for (const clazz of cssClasses) { - hostElement.classList.add(clazz); - } - bindLifecycleEvents(componentRef.instance, hostElement); - container.appendChild(hostElement); - - this.appRef.attachView(componentRef.hostView); - this.elRefMap.set(hostElement, componentRef); - return Promise.resolve(hostElement); + attachViewToDom(container: any, component: any, params?: any, cssClasses?: string[]): Promise { + return new Promise(resolve => { + this.zone.run(() => { + const el = attachView( + this.cfr, this.injector, this.appRef, this.elRefMap, + container, component, params, cssClasses + ); + resolve(el); + }); + }); } removeViewFromDom(_container: any, component: any): Promise { - const componentRef = this.elRefMap.get(component); - if (componentRef) { - componentRef.destroy(); - this.elRefMap.delete(component); - } - return Promise.resolve(); + return new Promise(resolve => { + this.zone.run(() => { + const componentRef = this.elRefMap.get(component); + if (componentRef) { + componentRef.destroy(); + this.elRefMap.delete(component); + } + resolve(); + }); + }); } } +export function attachView( + cfr: ComponentFactoryResolver, + injector: Injector, + appRef: ApplicationRef, + elRefMap: WeakMap, + container: any, component: any, data?: any, cssClasses?: string[]) { + const componentFactory = cfr.resolveComponentFactory(component); + const hostElement = document.createElement(componentFactory.selector); + if (data) { + Object.assign(hostElement, data); + } + + const childInjector = Injector.create([], injector); + const componentRef = componentFactory.create(childInjector, [], hostElement); + for (const clazz of cssClasses) { + hostElement.classList.add(clazz); + } + bindLifecycleEvents(componentRef.instance, hostElement); + container.appendChild(hostElement); + + appRef.attachView(componentRef.hostView); + elRefMap.set(hostElement, componentRef); + return hostElement; +} + const LIFECYCLES = [ ViewLifecycle.WillEnter, ViewLifecycle.DidEnter, diff --git a/angular/test/nav/src/app/no-routing-nav/pages/page-one.ts b/angular/test/nav/src/app/no-routing-nav/pages/page-one.ts index 802c871bb0..9fafcf2988 100755 --- a/angular/test/nav/src/app/no-routing-nav/pages/page-one.ts +++ b/angular/test/nav/src/app/no-routing-nav/pages/page-one.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { PageTwo } from './page-two'; +import { Nav } from '@ionic/angular'; @Component({ selector: 'page-one', @@ -29,9 +30,7 @@ export class PageOne { ionViewWillEnterDetection = 'initial'; ionViewDidEnterDetection = 'initial'; - constructor() { - - } + constructor(private nav: Nav) {} ngOnInit() { @@ -55,8 +54,7 @@ export class PageOne { }, 500); } - goToPageTwo() { - const nav = document.querySelector('ion-nav') as any; - nav.push(PageTwo).then(() => console.log('push complete')); + async goToPageTwo() { + await this.nav.push(PageTwo); } } diff --git a/core/src/components/action-sheet/action-sheet.tsx b/core/src/components/action-sheet/action-sheet.tsx index 9aad51c694..e544613730 100644 --- a/core/src/components/action-sheet/action-sheet.tsx +++ b/core/src/components/action-sheet/action-sheet.tsx @@ -1,12 +1,10 @@ import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Animation, AnimationBuilder, Config, CssClassMap } from '../../index'; - -import { createThemedClasses, getClassMap } from '../../utils/theme'; import { BACKDROP, OverlayEventDetail, OverlayInterface, dismiss, eventMethod, isCancel, present } from '../../utils/overlays'; +import { createThemedClasses, getClassMap } from '../../utils/theme'; import iosEnterAnimation from './animations/ios.enter'; import iosLeaveAnimation from './animations/ios.leave'; - import mdEnterAnimation from './animations/md.enter'; import mdLeaveAnimation from './animations/md.leave'; diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index 15c7f4ed50..caa55d4c21 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -1,11 +1,10 @@ import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Animation, AnimationBuilder, Config, CssClassMap } from '../../index'; -import { createThemedClasses, getClassMap } from '../../utils/theme'; import { BACKDROP, OverlayEventDetail, OverlayInterface, dismiss, eventMethod, isCancel, present } from '../../utils/overlays'; +import { createThemedClasses, getClassMap } from '../../utils/theme'; import iosEnterAnimation from './animations/ios.enter'; import iosLeaveAnimation from './animations/ios.leave'; - import mdEnterAnimation from './animations/md.enter'; import mdLeaveAnimation from './animations/md.leave';