mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix: consistently coerce boolean and number properties (#7283)
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import {UniqueSelectionDispatcher} from '@angular/cdk/collections';
|
||||
import {CdkAccordion} from './accordion';
|
||||
import {coerceBooleanProperty} from '@angular/cdk/coercion';
|
||||
|
||||
/** Used to generate unique ID for each accordion item. */
|
||||
let nextId = 0;
|
||||
@@ -41,8 +42,10 @@ export class CdkAccordionItem implements OnDestroy {
|
||||
|
||||
/** Whether the AccordionItem is expanded. */
|
||||
@Input()
|
||||
get expanded(): boolean { return this._expanded; }
|
||||
set expanded(expanded: boolean) {
|
||||
get expanded(): any { return this._expanded; }
|
||||
set expanded(expanded: any) {
|
||||
expanded = coerceBooleanProperty(expanded);
|
||||
|
||||
// Only emit events and update the internal value if the value changes.
|
||||
if (this._expanded !== expanded) {
|
||||
this._expanded = expanded;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
/** Coerces a data-bound value (typically a string) to a number. */
|
||||
export function coerceNumberProperty(value: any): number;
|
||||
export function coerceNumberProperty<D>(value: any, fallback: D): number | D;
|
||||
export function coerceNumberProperty(value: any, fallbackValue = 0) {
|
||||
// parseFloat(value) handles most of the cases we're interested in (it treats null, empty string,
|
||||
// and other non-number values as NaN, where Number just uses 0) but it considers the string
|
||||
|
||||
@@ -145,15 +145,22 @@ export class MatDatepicker<D> implements OnDestroy {
|
||||
* Whether the calendar UI is in touch mode. In touch mode the calendar opens in a dialog rather
|
||||
* than a popup and elements have more padding to allow for bigger touch targets.
|
||||
*/
|
||||
@Input() touchUi = false;
|
||||
@Input()
|
||||
get touchUi(): boolean {
|
||||
return this._touchUi;
|
||||
}
|
||||
set touchUi(value: boolean) {
|
||||
this._touchUi = coerceBooleanProperty(value);
|
||||
}
|
||||
private _touchUi = false;
|
||||
|
||||
/** Whether the datepicker pop-up should be disabled. */
|
||||
@Input()
|
||||
get disabled() {
|
||||
get disabled(): boolean {
|
||||
return this._disabled === undefined && this._datepickerInput ?
|
||||
this._datepickerInput.disabled : !!this._disabled;
|
||||
}
|
||||
set disabled(value: any) {
|
||||
set disabled(value: boolean) {
|
||||
const newValue = coerceBooleanProperty(value);
|
||||
|
||||
if (newValue !== this._disabled) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import {UniqueSelectionDispatcher} from '@angular/cdk/collections';
|
||||
import {CanDisable, mixinDisabled} from '@angular/material/core';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
import {MatAccordion} from './accordion';
|
||||
import {coerceBooleanProperty} from '@angular/cdk/coercion';
|
||||
|
||||
/** Workaround for https://github.com/angular/angular/issues/17849 */
|
||||
export const _CdkAccordionItem = CdkAccordionItem;
|
||||
@@ -91,8 +92,16 @@ export type MatExpansionPanelState = 'expanded' | 'collapsed';
|
||||
})
|
||||
export class MatExpansionPanel extends _MatExpansionPanelMixinBase
|
||||
implements CanDisable, OnChanges, OnDestroy {
|
||||
|
||||
/** Whether the toggle indicator should be hidden. */
|
||||
@Input() hideToggle: boolean = false;
|
||||
@Input()
|
||||
get hideToggle(): boolean {
|
||||
return this._hideToggle;
|
||||
}
|
||||
set hideToggle(value: boolean) {
|
||||
this._hideToggle = coerceBooleanProperty(value);
|
||||
}
|
||||
private _hideToggle = false;
|
||||
|
||||
/** Stream that emits for changes in `@Input` properties. */
|
||||
_inputChanges = new Subject<SimpleChanges>();
|
||||
|
||||
@@ -39,6 +39,7 @@ import {throwMatMenuInvalidPositionX, throwMatMenuInvalidPositionY} from './menu
|
||||
import {MatMenuItem} from './menu-item';
|
||||
import {MatMenuPanel} from './menu-panel';
|
||||
import {MenuPositionX, MenuPositionY} from './menu-positions';
|
||||
import {coerceBooleanProperty} from '@angular/cdk/coercion';
|
||||
|
||||
|
||||
/** Default `mat-menu` options that can be overridden. */
|
||||
@@ -122,7 +123,14 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
|
||||
@ContentChildren(MatMenuItem) items: QueryList<MatMenuItem>;
|
||||
|
||||
/** Whether the menu should overlap its trigger. */
|
||||
@Input() overlapTrigger = this._defaultOptions.overlapTrigger;
|
||||
@Input()
|
||||
set overlapTrigger(value: boolean) {
|
||||
this._overlapTrigger = coerceBooleanProperty(value);
|
||||
}
|
||||
get overlapTrigger(): boolean {
|
||||
return this._overlapTrigger;
|
||||
}
|
||||
private _overlapTrigger: boolean = this._defaultOptions.overlapTrigger;
|
||||
|
||||
/**
|
||||
* This method takes classes set on the host mat-menu element and applies them on the
|
||||
|
||||
@@ -124,7 +124,7 @@ export class MatSlideToggle extends _MatSlideToggleMixinBase implements OnDestro
|
||||
@Input()
|
||||
get checked(): boolean { return this._checked; }
|
||||
set checked(value) {
|
||||
this._checked = !!value;
|
||||
this._checked = coerceBooleanProperty(value);
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
/** An event will be dispatched each time the slide-toggle changes its value. */
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import {coerceBooleanProperty} from '@angular/cdk/coercion';
|
||||
import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
import {MatTab} from './tab';
|
||||
import {MatTabHeader} from './tab-header';
|
||||
@@ -109,7 +109,9 @@ export class MatTabGroup extends _MatTabGroupMixinBase implements AfterContentIn
|
||||
|
||||
/** The index of the active tab. */
|
||||
@Input()
|
||||
set selectedIndex(value: number | null) { this._indexToSelect = value; }
|
||||
set selectedIndex(value: number | null) {
|
||||
this._indexToSelect = coerceNumberProperty(value, null);
|
||||
}
|
||||
get selectedIndex(): number | null { return this._selectedIndex; }
|
||||
private _selectedIndex: number | null = null;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import {CanDisableRipple, mixinDisableRipple} from '@angular/material/core';
|
||||
import {merge} from 'rxjs/observable/merge';
|
||||
import {of as observableOf} from 'rxjs/observable/of';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
import {coerceNumberProperty} from '@angular/cdk/coercion';
|
||||
import {MatInkBar} from './ink-bar';
|
||||
import {MatTabLabelWrapper} from './tab-label-wrapper';
|
||||
import {ViewportRuler} from '@angular/cdk/scrolling';
|
||||
@@ -120,6 +121,7 @@ export class MatTabHeader extends _MatTabHeaderMixinBase
|
||||
@Input()
|
||||
get selectedIndex(): number { return this._selectedIndex; }
|
||||
set selectedIndex(value: number) {
|
||||
value = coerceNumberProperty(value);
|
||||
this._selectedIndexChanged = this._selectedIndex != value;
|
||||
this._selectedIndex = value;
|
||||
this._focusIndex = value;
|
||||
|
||||
Reference in New Issue
Block a user