Skip to content

Commit

Permalink
fix(button-toggle): error when check value is set via static attribut…
Browse files Browse the repository at this point in the history
…e in Ivy (#16587)

Fixes the button toggle throwing an error under Ivy, if its `checked` value is set via a static attribute (e.g. `<mat-button-toggle checked>`). The issue comes from the fact that in Ivy static inputs are set during creation, which means that the selection model isn't initialized yet.

Fixes #16471.
  • Loading branch information
crisbeto authored and jelbourn committed Jul 25, 2019
1 parent 174bf40 commit bd24369
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
14 changes: 14 additions & 0 deletions src/material/button-toggle/button-toggle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,20 @@ describe('MatButtonToggle without forms', () => {
expect(fixture.componentInstance.toggles.toArray()[1].checked).toBe(false);
expect(fixture.componentInstance.toggles.toArray()[2].checked).toBe(true);
});

it('should not throw if initial value is set during creation', () => {
const fixture = TestBed.createComponent(ButtonTogglesInsideButtonToggleGroupMultiple);

// In Ivy static inputs are set during creation. We simulate this by not calling
// `fixture.detectChanges` immediately, but getting a hold of the instance via the
// DebugElement and setting the value ourselves.
expect(() => {
const toggle = fixture.debugElement.query(By.css('mat-button-toggle')).componentInstance;
toggle.checked = true;
fixture.detectChanges();
}).not.toThrow();
});

});

@Component({
Expand Down
14 changes: 9 additions & 5 deletions src/material/button-toggle/button-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export class MatButtonToggleGroup implements ControlValueAccessor, OnInit, After

/** Selected button toggles in the group. */
get selected() {
const selected = this._selectionModel.selected;
const selected = this._selectionModel ? this._selectionModel.selected : [];
return this.multiple ? selected : (selected[0] || null);
}

Expand Down Expand Up @@ -276,10 +276,14 @@ export class MatButtonToggleGroup implements ControlValueAccessor, OnInit, After
(this.selected as MatButtonToggle).checked = false;
}

if (select) {
this._selectionModel.select(toggle);
if (this._selectionModel) {
if (select) {
this._selectionModel.select(toggle);
} else {
this._selectionModel.deselect(toggle);
}
} else {
this._selectionModel.deselect(toggle);
deferEvents = true;
}

// We need to defer in some cases in order to avoid "changed after checked errors", however
Expand All @@ -294,7 +298,7 @@ export class MatButtonToggleGroup implements ControlValueAccessor, OnInit, After

/** Checks whether a button toggle is selected. */
_isSelected(toggle: MatButtonToggle) {
return this._selectionModel.isSelected(toggle);
return this._selectionModel && this._selectionModel.isSelected(toggle);
}

/** Determines whether a button toggle should be checked on init. */
Expand Down

0 comments on commit bd24369

Please sign in to comment.