Skip to content

Commit 0e86fec

Browse files
committed
fix(select): throwing additional errors if ngModel fails to initialize
If the user has an `md-select` with an `ngModel` that doesn't have a name inside a form, the forms module will throw an error, however Material will also start throwing errors, which may cause confusion. These changes add a null check so our errors don't get mixed up with the forms error. Fixes #5402.
1 parent f73cc97 commit 0e86fec

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

src/lib/select/select.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<div class="mat-select-trigger" cdk-overlay-origin (click)="toggle()" #origin="cdkOverlayOrigin" #trigger>
22
<span
33
class="mat-select-placeholder"
4-
[class.mat-floating-placeholder]="_selectionModel.hasValue()"
4+
[class.mat-floating-placeholder]="_hasValue()"
55
[@transformPlaceholder]="_getPlaceholderAnimationState()"
66
[style.opacity]="_getPlaceholderOpacity()"
77
[style.width.px]="_selectedValueWidth"> {{ placeholder }} </span>
8-
<span class="mat-select-value" *ngIf="_selectionModel.hasValue()">
8+
<span class="mat-select-value" *ngIf="_hasValue()">
99
<span class="mat-select-value-text">{{ triggerValue }}</span>
1010
</span>
1111

src/lib/select/select.spec.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ describe('MdSelect', () => {
6363
BasicSelectWithTheming,
6464
ResetValuesSelect,
6565
FalsyValueSelect,
66-
SelectWithGroups
66+
SelectWithGroups,
67+
InvalidSelectInForm
6768
],
6869
providers: [
6970
{provide: OverlayContainer, useFactory: () => {
@@ -1942,6 +1943,17 @@ describe('MdSelect', () => {
19421943
}).not.toThrow();
19431944
}));
19441945

1946+
it('should not throw selection model-related errors in addition to the errors from ngModel',
1947+
async(() => {
1948+
const fixture = TestBed.createComponent(InvalidSelectInForm);
1949+
1950+
// The first change detection run will throw the "ngModel is missing a name" error.
1951+
expect(() => fixture.detectChanges()).toThrow();
1952+
1953+
// The second run shouldn't throw selection-model related errors.
1954+
expect(() => fixture.detectChanges()).not.toThrowError(/hasValue/g);
1955+
}));
1956+
19451957
});
19461958

19471959
describe('change event', () => {
@@ -2842,3 +2854,11 @@ class SelectWithGroups {
28422854
@ViewChild(MdSelect) select: MdSelect;
28432855
@ViewChildren(MdOption) options: QueryList<MdOption>;
28442856
}
2857+
2858+
2859+
@Component({
2860+
template: `<form><md-select [(ngModel)]="value"></md-select></form>`
2861+
})
2862+
class InvalidSelectInForm {
2863+
value: any;
2864+
}

src/lib/select/select.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
547547
this._setScrollTop();
548548
}
549549

550+
/** Whether the select has a value. */
551+
_hasValue(): boolean {
552+
return this._selectionModel && this._selectionModel.hasValue();
553+
}
554+
550555
/**
551556
* Sets the scroll position of the scroll container. This must be called after
552557
* the overlay pane is attached or the scroll container element will not yet be
@@ -771,7 +776,7 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
771776
// The farthest the panel can be scrolled before it hits the bottom
772777
const maxScroll = scrollContainerHeight - panelHeight;
773778

774-
if (this._selectionModel.hasValue()) {
779+
if (this._hasValue()) {
775780
let selectedOptionOffset = this._getOptionIndex(this._selectionModel.selected[0])!;
776781

777782
selectedOptionOffset += this._getLabelCountBeforeOption(selectedOptionOffset);

0 commit comments

Comments
 (0)