Skip to content

Commit 01c1bfd

Browse files
atscottthePunderWoman
authored andcommitted
fix(core): Ensure OnPush ancestors are marked dirty when events occur (#39833)
We currently only wrap the event listener in the function which ensures ancestors are marked for check when the listener is placed on an element that has a native method for listening to an event. We actually need to do this wrapping in all cases so that events that are attached to non-rendered template items (`ng-template` and `ng-container`) also mark ancestors for check when they receive the event. fixes #39832 PR Close #39833
1 parent 95ed2b0 commit 01c1bfd

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

packages/core/src/render3/instructions/listener.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ function listenerInternal(
193193
lCleanup.push(listenerFn);
194194
tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, useCapture);
195195
}
196+
} else {
197+
// Even if there is no native listener to add, we still need to wrap the listener so that OnPush
198+
// ancestors are marked dirty when an event occurs.
199+
listenerFn = wrapListener(tNode, lView, listenerFn, false /** preventDefault */);
196200
}
197201

198202
// subscribe to directive outputs

packages/core/test/acceptance/change_detection_spec.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99

1010
import {CommonModule} from '@angular/common';
11-
import {ApplicationRef, ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentFactoryResolver, ComponentRef, Directive, DoCheck, EmbeddedViewRef, ErrorHandler, Input, NgModule, OnInit, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
12-
import {ComponentFixture, TestBed} from '@angular/core/testing';
11+
import {ApplicationRef, ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentFactoryResolver, ComponentRef, Directive, DoCheck, EmbeddedViewRef, ErrorHandler, EventEmitter, Input, NgModule, OnInit, Output, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
12+
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
1313
import {expect} from '@angular/platform-browser/testing/src/matchers';
1414
import {ivyEnabled} from '@angular/private/testing';
1515
import {BehaviorSubject} from 'rxjs';
@@ -461,6 +461,41 @@ describe('change detection', () => {
461461
expect(comp.doCheckCount).toEqual(2);
462462
expect(fixture.nativeElement.textContent.trim()).toEqual('3 - 2 - Nancy');
463463
});
464+
465+
it('should check parent OnPush components when child directive on a template emits event',
466+
fakeAsync(() => {
467+
@Directive({
468+
selector: '[emitter]',
469+
})
470+
class Emitter {
471+
@Output() event = new EventEmitter<string>();
472+
473+
ngOnInit() {
474+
setTimeout(() => {
475+
this.event.emit('new message');
476+
});
477+
}
478+
}
479+
480+
481+
@Component({
482+
selector: 'my-app',
483+
template: '{{message}} <ng-template emitter (event)="message = $event"></ng-template>',
484+
changeDetection: ChangeDetectionStrategy.OnPush
485+
})
486+
class MyApp {
487+
message = 'initial message';
488+
}
489+
490+
const fixture = TestBed.configureTestingModule({declarations: [MyApp, Emitter]})
491+
.createComponent(MyApp);
492+
fixture.detectChanges();
493+
494+
expect(fixture.nativeElement.textContent.trim()).toEqual('initial message');
495+
tick();
496+
fixture.detectChanges();
497+
expect(fixture.nativeElement.textContent.trim()).toEqual('new message');
498+
}));
464499
});
465500

466501
describe('ChangeDetectorRef', () => {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy