Skip to content

Commit 67b009f

Browse files
crisbetommalerba
authored andcommitted
fix(button-toggle): indirect descendant buttons not picked up… (#17451)
Fixes button toggles that aren't direct descendants of the button group not being picked up in some cases.
1 parent c50aa21 commit 67b009f

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

src/material/button-toggle/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ ng_test_library(
5454
deps = [
5555
":button-toggle",
5656
"//src/cdk/testing",
57+
"@npm//@angular/common",
5758
"@npm//@angular/forms",
5859
"@npm//@angular/platform-browser",
5960
],

src/material/button-toggle/button-toggle.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {dispatchMouseEvent} from '@angular/cdk/testing';
22
import {Component, DebugElement, QueryList, ViewChild, ViewChildren} from '@angular/core';
3+
import {CommonModule} from '@angular/common';
34
import {ComponentFixture, fakeAsync, flush, TestBed, tick} from '@angular/core/testing';
45
import {FormControl, FormsModule, NgModel, ReactiveFormsModule} from '@angular/forms';
56
import {By} from '@angular/platform-browser';
@@ -15,10 +16,11 @@ describe('MatButtonToggle with forms', () => {
1516

1617
beforeEach(fakeAsync(() => {
1718
TestBed.configureTestingModule({
18-
imports: [MatButtonToggleModule, FormsModule, ReactiveFormsModule],
19+
imports: [MatButtonToggleModule, FormsModule, ReactiveFormsModule, CommonModule],
1920
declarations: [
2021
ButtonToggleGroupWithNgModel,
2122
ButtonToggleGroupWithFormControl,
23+
ButtonToggleGroupWithIndirectDescendantToggles,
2224
],
2325
});
2426

@@ -232,6 +234,24 @@ describe('MatButtonToggle with forms', () => {
232234
}));
233235

234236
});
237+
238+
it('should be able to pick up toggles that are not direct descendants', fakeAsync(() => {
239+
const fixture = TestBed.createComponent(ButtonToggleGroupWithIndirectDescendantToggles);
240+
fixture.detectChanges();
241+
242+
const button = fixture.nativeElement.querySelector('.mat-button-toggle button');
243+
const groupDebugElement = fixture.debugElement.query(By.directive(MatButtonToggleGroup))!;
244+
const groupInstance =
245+
groupDebugElement.injector.get<MatButtonToggleGroup>(MatButtonToggleGroup);
246+
247+
button.click();
248+
fixture.detectChanges();
249+
tick();
250+
251+
expect(groupInstance.value).toBe('red');
252+
expect(fixture.componentInstance.control.value).toBe('red');
253+
expect(groupInstance._buttonToggles.length).toBe(3);
254+
}));
235255
});
236256

237257
describe('MatButtonToggle without forms', () => {
@@ -966,6 +986,22 @@ class ButtonToggleGroupWithFormControl {
966986
control = new FormControl();
967987
}
968988

989+
@Component({
990+
// We need the `ngSwitch` so that there's a directive between the group and the toggles.
991+
template: `
992+
<mat-button-toggle-group [formControl]="control">
993+
<ng-container [ngSwitch]="true">
994+
<mat-button-toggle value="red">Value Red</mat-button-toggle>
995+
<mat-button-toggle value="green">Value Green</mat-button-toggle>
996+
<mat-button-toggle value="blue">Value Blue</mat-button-toggle>
997+
</ng-container>
998+
</mat-button-toggle-group>
999+
`
1000+
})
1001+
class ButtonToggleGroupWithIndirectDescendantToggles {
1002+
control = new FormControl();
1003+
}
1004+
9691005
/** Simple test component with an aria-label set. */
9701006
@Component({
9711007
template: `<mat-button-toggle aria-label="Super effective"></mat-button-toggle>`

src/material/button-toggle/button-toggle.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ export class MatButtonToggleGroup implements ControlValueAccessor, OnInit, After
131131
_onTouched: () => any = () => {};
132132

133133
/** Child button toggle buttons. */
134-
@ContentChildren(forwardRef(() => MatButtonToggle)) _buttonToggles: QueryList<MatButtonToggle>;
134+
@ContentChildren(forwardRef(() => MatButtonToggle), {
135+
// Note that this would technically pick up toggles
136+
// from nested groups, but that's not a case that we support.
137+
descendants: true
138+
}) _buttonToggles: QueryList<MatButtonToggle>;
135139

136140
/** The appearance for all the buttons in the group. */
137141
@Input() appearance: MatButtonToggleAppearance;

0 commit comments

Comments
 (0)