From 67b009f0475c60a27d18160ff8ab2742cb5581b3 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 22 Oct 2019 00:32:34 +0200 Subject: [PATCH] =?UTF-8?q?fix(button-toggle):=20indirect=20descendant=20b?= =?UTF-8?q?uttons=20not=20picked=20up=E2=80=A6=20(#17451)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes button toggles that aren't direct descendants of the button group not being picked up in some cases. --- src/material/button-toggle/BUILD.bazel | 1 + .../button-toggle/button-toggle.spec.ts | 38 ++++++++++++++++++- src/material/button-toggle/button-toggle.ts | 6 ++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/material/button-toggle/BUILD.bazel b/src/material/button-toggle/BUILD.bazel index f562fdd8fd17..88df9d933427 100644 --- a/src/material/button-toggle/BUILD.bazel +++ b/src/material/button-toggle/BUILD.bazel @@ -54,6 +54,7 @@ ng_test_library( deps = [ ":button-toggle", "//src/cdk/testing", + "@npm//@angular/common", "@npm//@angular/forms", "@npm//@angular/platform-browser", ], diff --git a/src/material/button-toggle/button-toggle.spec.ts b/src/material/button-toggle/button-toggle.spec.ts index 400825e6dd38..37d43d328def 100644 --- a/src/material/button-toggle/button-toggle.spec.ts +++ b/src/material/button-toggle/button-toggle.spec.ts @@ -1,5 +1,6 @@ import {dispatchMouseEvent} from '@angular/cdk/testing'; import {Component, DebugElement, QueryList, ViewChild, ViewChildren} from '@angular/core'; +import {CommonModule} from '@angular/common'; import {ComponentFixture, fakeAsync, flush, TestBed, tick} from '@angular/core/testing'; import {FormControl, FormsModule, NgModel, ReactiveFormsModule} from '@angular/forms'; import {By} from '@angular/platform-browser'; @@ -15,10 +16,11 @@ describe('MatButtonToggle with forms', () => { beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ - imports: [MatButtonToggleModule, FormsModule, ReactiveFormsModule], + imports: [MatButtonToggleModule, FormsModule, ReactiveFormsModule, CommonModule], declarations: [ ButtonToggleGroupWithNgModel, ButtonToggleGroupWithFormControl, + ButtonToggleGroupWithIndirectDescendantToggles, ], }); @@ -232,6 +234,24 @@ describe('MatButtonToggle with forms', () => { })); }); + + it('should be able to pick up toggles that are not direct descendants', fakeAsync(() => { + const fixture = TestBed.createComponent(ButtonToggleGroupWithIndirectDescendantToggles); + fixture.detectChanges(); + + const button = fixture.nativeElement.querySelector('.mat-button-toggle button'); + const groupDebugElement = fixture.debugElement.query(By.directive(MatButtonToggleGroup))!; + const groupInstance = + groupDebugElement.injector.get(MatButtonToggleGroup); + + button.click(); + fixture.detectChanges(); + tick(); + + expect(groupInstance.value).toBe('red'); + expect(fixture.componentInstance.control.value).toBe('red'); + expect(groupInstance._buttonToggles.length).toBe(3); + })); }); describe('MatButtonToggle without forms', () => { @@ -966,6 +986,22 @@ class ButtonToggleGroupWithFormControl { control = new FormControl(); } +@Component({ + // We need the `ngSwitch` so that there's a directive between the group and the toggles. + template: ` + + + Value Red + Value Green + Value Blue + + + ` +}) +class ButtonToggleGroupWithIndirectDescendantToggles { + control = new FormControl(); +} + /** Simple test component with an aria-label set. */ @Component({ template: `` diff --git a/src/material/button-toggle/button-toggle.ts b/src/material/button-toggle/button-toggle.ts index 4cef7a7e6f5c..d0a341fc9e45 100644 --- a/src/material/button-toggle/button-toggle.ts +++ b/src/material/button-toggle/button-toggle.ts @@ -131,7 +131,11 @@ export class MatButtonToggleGroup implements ControlValueAccessor, OnInit, After _onTouched: () => any = () => {}; /** Child button toggle buttons. */ - @ContentChildren(forwardRef(() => MatButtonToggle)) _buttonToggles: QueryList; + @ContentChildren(forwardRef(() => MatButtonToggle), { + // Note that this would technically pick up toggles + // from nested groups, but that's not a case that we support. + descendants: true + }) _buttonToggles: QueryList; /** The appearance for all the buttons in the group. */ @Input() appearance: MatButtonToggleAppearance;