From ad9ce5cb4117243f5f018e9da9db37d32c314050 Mon Sep 17 00:00:00 2001 From: Shannon Dunn Date: Tue, 13 Feb 2018 17:13:47 -0500 Subject: [PATCH] fix(upgrade): correctly handle downgraded `OnPush` components (#22209) Fixes #14286 PR Close #22209 --- .../src/common/downgrade_component_adapter.ts | 4 ++ .../integration/downgrade_component_spec.ts | 47 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/upgrade/src/common/downgrade_component_adapter.ts b/packages/upgrade/src/common/downgrade_component_adapter.ts index b5dfbfef2b..7d15d0c4a5 100644 --- a/packages/upgrade/src/common/downgrade_component_adapter.ts +++ b/packages/upgrade/src/common/downgrade_component_adapter.ts @@ -25,6 +25,7 @@ export class DowngradeComponentAdapter { private componentRef: ComponentRef; private component: any; private changeDetector: ChangeDetectorRef; + private viewChangeDetector: ChangeDetectorRef; constructor( private element: angular.IAugmentedJQuery, private attrs: angular.IAttributes, @@ -60,6 +61,7 @@ export class DowngradeComponentAdapter { this.componentRef = this.componentFactory.create(childInjector, projectableNodes, this.element[0]); + this.viewChangeDetector = this.componentRef.injector.get(ChangeDetectorRef); this.changeDetector = this.componentRef.changeDetectorRef; this.component = this.componentRef.instance; @@ -139,6 +141,8 @@ export class DowngradeComponentAdapter { (this.component).ngOnChanges(inputChanges !); } + this.viewChangeDetector.markForCheck(); + // If opted out of propagating digests, invoke change detection when inputs change. if (!propagateDigest) { detectChanges(); diff --git a/packages/upgrade/test/static/integration/downgrade_component_spec.ts b/packages/upgrade/test/static/integration/downgrade_component_spec.ts index d6254b7b1e..810d604c34 100644 --- a/packages/upgrade/test/static/integration/downgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_component_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {ChangeDetectorRef, Compiler, Component, ComponentFactoryResolver, Directive, ElementRef, EventEmitter, Injector, Input, NgModule, NgModuleRef, OnChanges, OnDestroy, Output, SimpleChanges, destroyPlatform} from '@angular/core'; +import {ChangeDetectionStrategy, ChangeDetectorRef, Compiler, Component, ComponentFactoryResolver, Directive, ElementRef, EventEmitter, Injector, Input, NgModule, NgModuleRef, OnChanges, OnDestroy, Output, SimpleChanges, destroyPlatform} from '@angular/core'; import {async, fakeAsync, tick} from '@angular/core/testing'; import {BrowserModule} from '@angular/platform-browser'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; @@ -148,6 +148,51 @@ withEachNg1Version(() => { }); })); + it('should bind properties to onpush components', async(() => { + const ng1Module = + angular.module('ng1', []).value('$exceptionHandler', (err: any) => { + throw err; + }).run(($rootScope: angular.IScope) => { + $rootScope['dataB'] = 'B'; + }); + + @Component({ + selector: 'ng2', + inputs: ['oneWayB'], + template: 'oneWayB: {{oneWayB}}', + changeDetection: ChangeDetectionStrategy.OnPush + }) + + class Ng2Component { + ngOnChangesCount = 0; + oneWayB = '?'; + } + + ng1Module.directive('ng2', downgradeComponent({ + component: Ng2Component, + })); + + @NgModule({ + declarations: [Ng2Component], + entryComponents: [Ng2Component], + imports: [BrowserModule, UpgradeModule] + }) + class Ng2Module { + ngDoBootstrap() {} + } + + const element = html(` +
+ +
`); + + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => { + expect(multiTrim(document.body.textContent)).toEqual('oneWayB: B'); + $apply(upgrade, 'dataB= "everyone"'); + expect(multiTrim(document.body.textContent)).toEqual('oneWayB: everyone'); + }); + })); + it('should support two-way binding and event listener', async(() => { const listenerSpy = jasmine.createSpy('$rootScope.listener'); const ng1Module = angular.module('ng1', []).run(($rootScope: angular.IScope) => {