Skip to content

Commit 881274b

Browse files
andy9775mmalerba
authored andcommitted
bug(cdk-experimental): Unsubscribe MenuItem subscriptions
Multiple MenuItems may be loaded on a loop so we want to unsubscribe and not rely on parents destruction
1 parent cc92ee1 commit 881274b

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

src/cdk-experimental/menu/menu-item.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Directive, Output, Input, AfterContentInit, EventEmitter} from '@angular/core';
9+
import {Directive, Output, Input, AfterContentInit, EventEmitter, OnDestroy} from '@angular/core';
1010
import {coerceBooleanProperty, BooleanInput} from '@angular/cdk/coercion';
1111
import {CdkMenuPanel} from './menu-panel';
1212
import {CdkMenuGroup} from './menu-group';
1313
import {MenuItem} from './menu-item-interface';
14+
import {takeUntil} from 'rxjs/operators';
1415

1516
/**
1617
* Directive which provides behavior for an element which when clicked:
@@ -36,7 +37,7 @@ import {MenuItem} from './menu-item-interface';
3637
'[attr.aria-disabled]': 'disabled || null',
3738
},
3839
})
39-
export class CdkMenuItem implements AfterContentInit, MenuItem {
40+
export class CdkMenuItem implements AfterContentInit, MenuItem, OnDestroy {
4041
/** Template reference variable to the menu this trigger opens */
4142
@Input('cdkMenuTriggerFor') _menuPanel?: CdkMenuPanel;
4243

@@ -66,6 +67,9 @@ export class CdkMenuItem implements AfterContentInit, MenuItem {
6667
/** Emits when the attached submenu is opened */
6768
@Output() opened: EventEmitter<void> = new EventEmitter();
6869

70+
/** Emits when the component gets destroyed */
71+
private readonly _destroyed: EventEmitter<void> = new EventEmitter();
72+
6973
constructor(
7074
/** reference a parent CdkMenuGroup component */
7175
private readonly _menuGroup: CdkMenuGroup
@@ -74,7 +78,9 @@ export class CdkMenuItem implements AfterContentInit, MenuItem {
7478
/** Configure event subscriptions */
7579
ngAfterContentInit() {
7680
if (this.role !== 'menuitem') {
77-
this._menuGroup.change.subscribe((button: CdkMenuItem) => this._toggleCheckedState(button));
81+
this._menuGroup.change
82+
.pipe(takeUntil(this._destroyed))
83+
.subscribe((button: MenuItem) => this._toggleCheckedState(button));
7884
}
7985
}
8086

@@ -109,14 +115,19 @@ export class CdkMenuItem implements AfterContentInit, MenuItem {
109115
/**
110116
* Toggle the checked state of the menuitemradio or menuitemcheckbox component
111117
*/
112-
private _toggleCheckedState(selected: CdkMenuItem) {
118+
private _toggleCheckedState(selected: MenuItem) {
113119
if (this.role === 'menuitemradio') {
114120
this.checked = selected === this;
115121
} else if (this.role === 'menuitemcheckbox' && selected === this) {
116122
this.checked = !this.checked;
117123
}
118124
}
119125

126+
ngOnDestroy() {
127+
this._destroyed.next();
128+
this._destroyed.complete();
129+
}
130+
120131
static ngAcceptInputType_checked: BooleanInput;
121132
static ngAcceptInputType_disabled: BooleanInput;
122133
}

0 commit comments

Comments
 (0)