PR Close #20538
This commit is contained in:
parent
2a9d2bacd5
commit
a740e4f00a
|
@ -203,16 +203,26 @@ export class DomEventsPlugin extends EventManagerPlugin {
|
|||
// just call native removeEventListener
|
||||
return target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]);
|
||||
}
|
||||
// fix issue 20532, should be able to remove
|
||||
// listener which was added inside of ngZone
|
||||
let found = false;
|
||||
for (let i = 0; i < taskDatas.length; i++) {
|
||||
// remove listener from taskDatas if the callback equals
|
||||
if (taskDatas[i].handler === callback) {
|
||||
found = true;
|
||||
taskDatas.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (taskDatas.length === 0) {
|
||||
// all listeners are removed, we can remove the globalListener from target
|
||||
underlyingRemove.apply(target, [eventName, globalListener, false]);
|
||||
if (found) {
|
||||
if (taskDatas.length === 0) {
|
||||
// all listeners are removed, we can remove the globalListener from target
|
||||
underlyingRemove.apply(target, [eventName, globalListener, false]);
|
||||
}
|
||||
} else {
|
||||
// not found in taskDatas, the callback may be added inside of ngZone
|
||||
// use native remove listener to remove the calback
|
||||
target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,6 +255,46 @@ export function main() {
|
|||
expect(receivedEvents).toEqual([]);
|
||||
});
|
||||
|
||||
it('should be able to remove event listener which was added inside of ngZone', () => {
|
||||
const Zone = (window as any)['Zone'];
|
||||
|
||||
const element = el('<div><div></div></div>');
|
||||
getDOM().appendChild(doc.body, element);
|
||||
const dispatchedEvent = getDOM().createMouseEvent('click');
|
||||
let receivedEvents: any[] /** TODO #9100 */ = [];
|
||||
let receivedZones: any[] = [];
|
||||
const handler1 = (e: any /** TODO #9100 */) => {
|
||||
receivedEvents.push(e);
|
||||
receivedZones.push(Zone.current.name);
|
||||
};
|
||||
const handler2 = (e: any /** TODO #9100 */) => {
|
||||
receivedEvents.push(e);
|
||||
receivedZones.push(Zone.current.name);
|
||||
};
|
||||
const manager = new EventManager([domEventPlugin], new FakeNgZone());
|
||||
|
||||
let remover1 = null;
|
||||
let remover2 = null;
|
||||
// handler1 is added in root zone
|
||||
Zone.root.run(() => { remover1 = manager.addEventListener(element, 'click', handler1); });
|
||||
// handler2 is added in 'angular' zone
|
||||
Zone.root.fork({name: 'fakeAngularZone', properties: {isAngularZone: true}}).run(() => {
|
||||
remover2 = manager.addEventListener(element, 'click', handler2);
|
||||
});
|
||||
getDOM().dispatchEvent(element, dispatchedEvent);
|
||||
expect(receivedEvents).toEqual([dispatchedEvent, dispatchedEvent]);
|
||||
expect(receivedZones).toEqual([Zone.root.name, 'fakeAngularZone']);
|
||||
|
||||
receivedEvents = [];
|
||||
remover1 && remover1();
|
||||
remover2 && remover2();
|
||||
getDOM().dispatchEvent(element, dispatchedEvent);
|
||||
// handler1 and handler2 are added in different zone
|
||||
// one is angular zone, the other is not
|
||||
// should still be able to remove them correctly
|
||||
expect(receivedEvents).toEqual([]);
|
||||
});
|
||||
|
||||
it('should run blackListedEvents handler outside of ngZone', () => {
|
||||
const Zone = (window as any)['Zone'];
|
||||
const element = el('<div><div></div></div>');
|
||||
|
|
Loading…
Reference in New Issue