Skip to content

fix(collections): clean up UniqueSelectionDispatcher listeners on destroy #9673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions src/cdk/collections/unique-selection-dispatcher.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,36 @@ import {UniqueSelectionDispatcher} from './unique-selection-dispatcher';


describe('Unique selection dispatcher', () => {
let dispatcher: UniqueSelectionDispatcher;

describe('register', () => {
it('once unregistered the listener must not be called on notify', (done) => {
let dispatcher: UniqueSelectionDispatcher = new UniqueSelectionDispatcher();
let called = false;
beforeEach(() => dispatcher = new UniqueSelectionDispatcher());

// Register first listener
dispatcher.listen(() => {
called = true;
});
it('should notify registered listeners', () => {
const spy = jasmine.createSpy('listen handler');

// Register a listener
let deregisterFn = dispatcher.listen(() => {
done.fail('Should not be called');
});
dispatcher.listen(spy);
dispatcher.notify('id', 'name');

// Unregister
deregisterFn();
expect(spy).toHaveBeenCalledWith('id', 'name');
});

it('should not notify unregistered listeners', () => {
const spy = jasmine.createSpy('listen handler');
const unregister = dispatcher.listen(spy);

unregister();
dispatcher.notify('id', 'name');

expect(spy).not.toHaveBeenCalled();
});

// Call registered listeners
dispatcher.notify('testId', 'testName');
it('should remove all listeners when destroyed', () => {
const spy = jasmine.createSpy('listen handler');
dispatcher.listen(spy);

expect(called).toBeTruthy('Registered listener must be called.');
dispatcher.ngOnDestroy();
dispatcher.notify('id', 'name');

done();
});
expect(spy).not.toHaveBeenCalled();
});
});
8 changes: 6 additions & 2 deletions src/cdk/collections/unique-selection-dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Injectable, Optional, SkipSelf} from '@angular/core';
import {Injectable, Optional, SkipSelf, OnDestroy} from '@angular/core';


// Users of the Dispatcher never need to see this type, but TypeScript requires it to be exported.
Expand All @@ -22,7 +22,7 @@ export type UniqueSelectionDispatcherListener = (id: string, name: string) => vo
* less error-prone if they are simply passed through when the events occur.
*/
@Injectable()
export class UniqueSelectionDispatcher {
export class UniqueSelectionDispatcher implements OnDestroy {
private _listeners: UniqueSelectionDispatcherListener[] = [];

/**
Expand All @@ -48,6 +48,10 @@ export class UniqueSelectionDispatcher {
});
};
}

ngOnDestroy() {
this._listeners = [];
}
}

/** @docs-private */
Expand Down