fix(upgrade): correctly handle downgraded `OnPush` components (#22209)
Fixes #14286 PR Close #22209
This commit is contained in:
parent
7a1c43733b
commit
ad9ce5cb41
|
@ -25,6 +25,7 @@ export class DowngradeComponentAdapter {
|
||||||
private componentRef: ComponentRef<any>;
|
private componentRef: ComponentRef<any>;
|
||||||
private component: any;
|
private component: any;
|
||||||
private changeDetector: ChangeDetectorRef;
|
private changeDetector: ChangeDetectorRef;
|
||||||
|
private viewChangeDetector: ChangeDetectorRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private element: angular.IAugmentedJQuery, private attrs: angular.IAttributes,
|
private element: angular.IAugmentedJQuery, private attrs: angular.IAttributes,
|
||||||
|
@ -60,6 +61,7 @@ export class DowngradeComponentAdapter {
|
||||||
|
|
||||||
this.componentRef =
|
this.componentRef =
|
||||||
this.componentFactory.create(childInjector, projectableNodes, this.element[0]);
|
this.componentFactory.create(childInjector, projectableNodes, this.element[0]);
|
||||||
|
this.viewChangeDetector = this.componentRef.injector.get(ChangeDetectorRef);
|
||||||
this.changeDetector = this.componentRef.changeDetectorRef;
|
this.changeDetector = this.componentRef.changeDetectorRef;
|
||||||
this.component = this.componentRef.instance;
|
this.component = this.componentRef.instance;
|
||||||
|
|
||||||
|
@ -139,6 +141,8 @@ export class DowngradeComponentAdapter {
|
||||||
(<OnChanges>this.component).ngOnChanges(inputChanges !);
|
(<OnChanges>this.component).ngOnChanges(inputChanges !);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.viewChangeDetector.markForCheck();
|
||||||
|
|
||||||
// If opted out of propagating digests, invoke change detection when inputs change.
|
// If opted out of propagating digests, invoke change detection when inputs change.
|
||||||
if (!propagateDigest) {
|
if (!propagateDigest) {
|
||||||
detectChanges();
|
detectChanges();
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {async, fakeAsync, tick} from '@angular/core/testing';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
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(`
|
||||||
|
<div>
|
||||||
|
<ng2 [one-way-b]="dataB"></ng2>
|
||||||
|
</div>`);
|
||||||
|
|
||||||
|
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(() => {
|
it('should support two-way binding and event listener', async(() => {
|
||||||
const listenerSpy = jasmine.createSpy('$rootScope.listener');
|
const listenerSpy = jasmine.createSpy('$rootScope.listener');
|
||||||
const ng1Module = angular.module('ng1', []).run(($rootScope: angular.IScope) => {
|
const ng1Module = angular.module('ng1', []).run(($rootScope: angular.IScope) => {
|
||||||
|
|
Loading…
Reference in New Issue