Skip to content

Commit 72be295

Browse files
committed
fix(material/select): option active styling not removed when value is changed programmatically
If an option is selected by the user and the value is changed programmatically afterwards, we weren't removing the active state from the previous option. This seems to be a regression from #19970. These changes resolve the issue and preserve the fix from #19970 by resetting the active styling manually.
1 parent e99ca0a commit 72be295

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

src/material-experimental/mdc-select/select.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,39 @@ describe('MDC-based MatSelect', () => {
10981098
expect(options[1].getAttribute('aria-disabled')).toEqual('false');
10991099
expect(options[2].getAttribute('aria-disabled')).toEqual('false');
11001100
}));
1101+
1102+
it('should remove the active state from options that have been deselected while closed',
1103+
fakeAsync(() => {
1104+
let activeOptions = options.filter(option => {
1105+
return option.classList.contains('mat-mdc-option-active');
1106+
});
1107+
expect(activeOptions).toEqual([options[0]],
1108+
'Expected first option to have active styles.');
1109+
1110+
options[1].click();
1111+
fixture.detectChanges();
1112+
trigger.click();
1113+
fixture.detectChanges();
1114+
flush();
1115+
1116+
activeOptions = options.filter(option => {
1117+
return option.classList.contains('mat-mdc-option-active');
1118+
});
1119+
expect(activeOptions).toEqual([options[1]],
1120+
'Expected only selected option to be marked as active after it is clicked.');
1121+
1122+
fixture.componentInstance.control.setValue(fixture.componentInstance.foods[7].value);
1123+
fixture.detectChanges();
1124+
trigger.click();
1125+
fixture.detectChanges();
1126+
flush();
1127+
1128+
activeOptions = options.filter(option => {
1129+
return option.classList.contains('mat-mdc-option-active');
1130+
});
1131+
expect(activeOptions).toEqual([options[7]],
1132+
'Expected only selected option to be marked as active after the value has changed.');
1133+
}));
11011134
});
11021135

11031136
describe('for option groups', () => {

src/material/select/select.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,33 @@ describe('MatSelect', () => {
10661066
expect(options[1].getAttribute('aria-disabled')).toEqual('false');
10671067
expect(options[2].getAttribute('aria-disabled')).toEqual('false');
10681068
}));
1069+
1070+
it('should remove the active state from options that have been deselected while closed',
1071+
fakeAsync(() => {
1072+
let activeOptions = options.filter(option => option.classList.contains('mat-active'));
1073+
expect(activeOptions).toEqual([options[0]],
1074+
'Expected first option to have active styles.');
1075+
1076+
options[1].click();
1077+
fixture.detectChanges();
1078+
trigger.click();
1079+
fixture.detectChanges();
1080+
flush();
1081+
1082+
activeOptions = options.filter(option => option.classList.contains('mat-active'));
1083+
expect(activeOptions).toEqual([options[1]],
1084+
'Expected only selected option to be marked as active after it is clicked.');
1085+
1086+
fixture.componentInstance.control.setValue(fixture.componentInstance.foods[7].value);
1087+
fixture.detectChanges();
1088+
trigger.click();
1089+
fixture.detectChanges();
1090+
flush();
1091+
1092+
activeOptions = options.filter(option => option.classList.contains('mat-active'));
1093+
expect(activeOptions).toEqual([options[7]],
1094+
'Expected only selected option to be marked as active after the value has changed.');
1095+
}));
10691096
});
10701097

10711098
describe('for option groups', () => {

src/material/select/select.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,16 +813,17 @@ export abstract class _MatSelectBase<C> extends _MatSelectMixinBase implements A
813813
* found with the designated value, the select trigger is cleared.
814814
*/
815815
private _setSelectionByValue(value: any | any[]): void {
816+
this._selectionModel.selected.forEach(option => option.setInactiveStyles());
817+
this._selectionModel.clear();
818+
816819
if (this.multiple && value) {
817820
if (!Array.isArray(value) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
818821
throw getMatSelectNonArrayValueError();
819822
}
820823

821-
this._selectionModel.clear();
822824
value.forEach((currentValue: any) => this._selectValue(currentValue));
823825
this._sortValues();
824826
} else {
825-
this._selectionModel.clear();
826827
const correspondingOption = this._selectValue(value);
827828

828829
// Shift focus to the active item. Note that we shouldn't do this in multiple

0 commit comments

Comments
 (0)