@angular/material
Version:
Angular Material
1,039 lines (1,033 loc) • 88.4 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/cdk/overlay'), require('@angular/common'), require('@angular/core'), require('@angular/material/core'), require('@angular/material/form-field'), require('@angular/cdk/scrolling'), require('@angular/cdk/a11y'), require('@angular/cdk/bidi'), require('@angular/cdk/coercion'), require('@angular/cdk/collections'), require('@angular/cdk/keycodes'), require('@angular/forms'), require('rxjs'), require('rxjs/operators'), require('@angular/animations')) :
typeof define === 'function' && define.amd ? define('@angular/material/select', ['exports', '@angular/cdk/overlay', '@angular/common', '@angular/core', '@angular/material/core', '@angular/material/form-field', '@angular/cdk/scrolling', '@angular/cdk/a11y', '@angular/cdk/bidi', '@angular/cdk/coercion', '@angular/cdk/collections', '@angular/cdk/keycodes', '@angular/forms', 'rxjs', 'rxjs/operators', '@angular/animations'], factory) :
(global = global || self, factory((global.ng = global.ng || {}, global.ng.material = global.ng.material || {}, global.ng.material.select = {}), global.ng.cdk.overlay, global.ng.common, global.ng.core, global.ng.material.core, global.ng.material.formField, global.ng.cdk.scrolling, global.ng.cdk.a11y, global.ng.cdk.bidi, global.ng.cdk.coercion, global.ng.cdk.collections, global.ng.cdk.keycodes, global.ng.forms, global.rxjs, global.rxjs.operators, global.ng.animations));
}(this, (function (exports, overlay, common, core, core$1, formField, scrolling, a11y, bidi, coercion, collections, keycodes, forms, rxjs, operators, animations) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (Object.prototype.hasOwnProperty.call(b, p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); };
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
return Reflect.metadata(metadataKey, metadataValue);
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try {
step(generator.next(value));
}
catch (e) {
reject(e);
} }
function rejected(value) { try {
step(generator["throw"](value));
}
catch (e) {
reject(e);
} }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function () { if (t[0] & 1)
throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
return t;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
}
catch (e) {
op = [6, e];
y = 0;
}
finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
}
}
var __createBinding = Object.create ? (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
}) : (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
o[k2] = m[k];
});
function __exportStar(m, o) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
__createBinding(o, m, p);
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m)
return m.call(o);
if (o && typeof o.length === "number")
return {
next: function () {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
/** @deprecated */
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/** @deprecated */
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
function __spreadArray(to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
}
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n])
i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try {
step(g[n](v));
}
catch (e) {
settle(q[0][3], e);
} }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length)
resume(q[0][0], q[0][1]); }
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}
function __asyncValues(o) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) {
Object.defineProperty(cooked, "raw", { value: raw });
}
else {
cooked.raw = raw;
}
return cooked;
}
;
var __setModuleDefault = Object.create ? (function (o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function (o, v) {
o["default"] = v;
};
function __importStar(mod) {
if (mod && mod.__esModule)
return mod;
var result = {};
if (mod != null)
for (var k in mod)
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
__createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}
function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}
function __classPrivateFieldGet(receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
}
function __classPrivateFieldSet(receiver, privateMap, value) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
return value;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* The following are all the animations for the mat-select component, with each
* const containing the metadata for one animation.
*
* The values below match the implementation of the AngularJS Material mat-select animation.
* @docs-private
*/
var matSelectAnimations = {
/**
* This animation ensures the select's overlay panel animation (transformPanel) is called when
* closing the select.
* This is needed due to https://github.com/angular/angular/issues/23302
*/
transformPanelWrap: animations.trigger('transformPanelWrap', [
animations.transition('* => void', animations.query('@transformPanel', [animations.animateChild()], { optional: true }))
]),
/**
* This animation transforms the select's overlay panel on and off the page.
*
* When the panel is attached to the DOM, it expands its width by the amount of padding, scales it
* up to 100% on the Y axis, fades in its border, and translates slightly up and to the
* side to ensure the option text correctly overlaps the trigger text.
*
* When the panel is removed from the DOM, it simply fades out linearly.
*/
transformPanel: animations.trigger('transformPanel', [
animations.state('void', animations.style({
transform: 'scaleY(0.8)',
minWidth: '100%',
opacity: 0
})),
animations.state('showing', animations.style({
opacity: 1,
minWidth: 'calc(100% + 32px)',
transform: 'scaleY(1)'
})),
animations.state('showing-multiple', animations.style({
opacity: 1,
minWidth: 'calc(100% + 64px)',
transform: 'scaleY(1)'
})),
animations.transition('void => *', animations.animate('120ms cubic-bezier(0, 0, 0.2, 1)')),
animations.transition('* => void', animations.animate('100ms 25ms linear', animations.style({ opacity: 0 })))
])
};
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Returns an exception to be thrown when attempting to change a select's `multiple` option
* after initialization.
* @docs-private
*/
function getMatSelectDynamicMultipleError() {
return Error('Cannot change `multiple` mode of select after initialization.');
}
/**
* Returns an exception to be thrown when attempting to assign a non-array value to a select
* in `multiple` mode. Note that `undefined` and `null` are still valid values to allow for
* resetting the value.
* @docs-private
*/
function getMatSelectNonArrayValueError() {
return Error('Value must be an array in multiple-selection mode.');
}
/**
* Returns an exception to be thrown when assigning a non-function value to the comparator
* used to determine if a value corresponds to an option. Note that whether the function
* actually takes two values and returns a boolean is not checked.
*/
function getMatSelectNonFunctionValueError() {
return Error('`compareWith` must be a function.');
}
var nextUniqueId = 0;
/**
* The following style constants are necessary to save here in order
* to properly calculate the alignment of the selected option over
* the trigger element.
*/
/**
* The max height of the select's overlay panel.
* @deprecated To be turned into a private variable.
* @breaking-change 12.0.0
*/
var SELECT_PANEL_MAX_HEIGHT = 256;
/**
* The panel's padding on the x-axis.
* @deprecated To be turned into a private variable.
* @breaking-change 12.0.0
*/
var SELECT_PANEL_PADDING_X = 16;
/**
* The panel's x axis padding if it is indented (e.g. there is an option group).
* @deprecated To be turned into a private variable.
* @breaking-change 12.0.0
*/
var SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;
/**
* The height of the select items in `em` units.
* @deprecated To be turned into a private variable.
* @breaking-change 12.0.0
*/
var SELECT_ITEM_HEIGHT_EM = 3;
// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.
/**
* Distance between the panel edge and the option text in
* multi-selection mode.
*
* Calculated as:
* (SELECT_PANEL_PADDING_X * 1.5) + 16 = 40
* The padding is multiplied by 1.5 because the checkbox's margin is half the padding.
* The checkbox width is 16px.
*
* @deprecated To be turned into a private variable.
* @breaking-change 12.0.0
*/
var SELECT_MULTIPLE_PANEL_PADDING_X = SELECT_PANEL_PADDING_X * 1.5 + 16;
/**
* The select panel will only "fit" inside the viewport if it is positioned at
* this value or more away from the viewport boundary.
*
* @deprecated To be turned into a private variable.
* @breaking-change 12.0.0
*/
var SELECT_PANEL_VIEWPORT_PADDING = 8;
/** Injection token that determines the scroll handling while a select is open. */
var MAT_SELECT_SCROLL_STRATEGY = new core.InjectionToken('mat-select-scroll-strategy');
/** @docs-private */
function MAT_SELECT_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
return function () { return overlay.scrollStrategies.reposition(); };
}
/** Injection token that can be used to provide the default options the select module. */
var MAT_SELECT_CONFIG = new core.InjectionToken('MAT_SELECT_CONFIG');
/** @docs-private */
var MAT_SELECT_SCROLL_STRATEGY_PROVIDER = {
provide: MAT_SELECT_SCROLL_STRATEGY,
deps: [overlay.Overlay],
useFactory: MAT_SELECT_SCROLL_STRATEGY_PROVIDER_FACTORY,
};
/** Change event object that is emitted when the select value has changed. */
var MatSelectChange = /** @class */ (function () {
function MatSelectChange(
/** Reference to the select that emitted the change event. */
source,
/** Current value of the select that emitted the event. */
value) {
this.source = source;
this.value = value;
}
return MatSelectChange;
}());
// Boilerplate for applying mixins to MatSelect.
/** @docs-private */
var MatSelectBase = /** @class */ (function () {
function MatSelectBase(_elementRef, _defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl) {
this._elementRef = _elementRef;
this._defaultErrorStateMatcher = _defaultErrorStateMatcher;
this._parentForm = _parentForm;
this._parentFormGroup = _parentFormGroup;
this.ngControl = ngControl;
}
return MatSelectBase;
}());
var _MatSelectMixinBase = core$1.mixinDisableRipple(core$1.mixinTabIndex(core$1.mixinDisabled(core$1.mixinErrorState(MatSelectBase))));
/**
* Injection token that can be used to reference instances of `MatSelectTrigger`. It serves as
* alternative token to the actual `MatSelectTrigger` class which could cause unnecessary
* retention of the class and its directive metadata.
*/
var MAT_SELECT_TRIGGER = new core.InjectionToken('MatSelectTrigger');
/**
* Allows the user to customize the trigger that is displayed when the select has a value.
*/
var MatSelectTrigger = /** @class */ (function () {
function MatSelectTrigger() {
}
return MatSelectTrigger;
}());
MatSelectTrigger.decorators = [
{ type: core.Directive, args: [{
selector: 'mat-select-trigger',
providers: [{ provide: MAT_SELECT_TRIGGER, useExisting: MatSelectTrigger }],
},] }
];
/** Base class with all of the `MatSelect` functionality. */
var _MatSelectBase = /** @class */ (function (_super) {
__extends(_MatSelectBase, _super);
function _MatSelectBase(_viewportRuler, _changeDetectorRef, _ngZone, _defaultErrorStateMatcher, elementRef, _dir, _parentForm, _parentFormGroup, _parentFormField, ngControl, tabIndex, scrollStrategyFactory, _liveAnnouncer, _defaultOptions) {
var _this = this;
var _a, _b, _c;
_this = _super.call(this, elementRef, _defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl) || this;
_this._viewportRuler = _viewportRuler;
_this._changeDetectorRef = _changeDetectorRef;
_this._ngZone = _ngZone;
_this._dir = _dir;
_this._parentFormField = _parentFormField;
_this.ngControl = ngControl;
_this._liveAnnouncer = _liveAnnouncer;
_this._defaultOptions = _defaultOptions;
/** Whether or not the overlay panel is open. */
_this._panelOpen = false;
/** Comparison function to specify which option is displayed. Defaults to object equality. */
_this._compareWith = function (o1, o2) { return o1 === o2; };
/** Unique id for this input. */
_this._uid = "mat-select-" + nextUniqueId++;
/** Current `ariar-labelledby` value for the select trigger. */
_this._triggerAriaLabelledBy = null;
/** Emits whenever the component is destroyed. */
_this._destroy = new rxjs.Subject();
/** `View -> model callback called when value changes` */
_this._onChange = function () { };
/** `View -> model callback called when select has been touched` */
_this._onTouched = function () { };
/** ID for the DOM node containing the select's value. */
_this._valueId = "mat-select-value-" + nextUniqueId++;
/** Emits when the panel element is finished transforming in. */
_this._panelDoneAnimatingStream = new rxjs.Subject();
_this._overlayPanelClass = ((_a = _this._defaultOptions) === null || _a === void 0 ? void 0 : _a.overlayPanelClass) || '';
_this._focused = false;
/** A name for this control that can be used by `mat-form-field`. */
_this.controlType = 'mat-select';
_this._required = false;
_this._multiple = false;
_this._disableOptionCentering = (_c = (_b = _this._defaultOptions) === null || _b === void 0 ? void 0 : _b.disableOptionCentering) !== null && _c !== void 0 ? _c : false;
/** Aria label of the select. */
_this.ariaLabel = '';
/** Combined stream of all of the child options' change events. */
_this.optionSelectionChanges = rxjs.defer(function () {
var options = _this.options;
if (options) {
return options.changes.pipe(operators.startWith(options), operators.switchMap(function () { return rxjs.merge.apply(void 0, __spread(options.map(function (option) { return option.onSelectionChange; }))); }));
}
return _this._ngZone.onStable
.pipe(operators.take(1), operators.switchMap(function () { return _this.optionSelectionChanges; }));
});
/** Event emitted when the select panel has been toggled. */
_this.openedChange = new core.EventEmitter();
/** Event emitted when the select has been opened. */
_this._openedStream = _this.openedChange.pipe(operators.filter(function (o) { return o; }), operators.map(function () { }));
/** Event emitted when the select has been closed. */
_this._closedStream = _this.openedChange.pipe(operators.filter(function (o) { return !o; }), operators.map(function () { }));
/** Event emitted when the selected value has been changed by the user. */
_this.selectionChange = new core.EventEmitter();
/**
* Event that emits whenever the raw value of the select changes. This is here primarily
* to facilitate the two-way binding for the `value` input.
* @docs-private
*/
_this.valueChange = new core.EventEmitter();
if (_this.ngControl) {
// Note: we provide the value accessor through here, instead of
// the `providers` to avoid running into a circular import.
_this.ngControl.valueAccessor = _this;
}
// Note that we only want to set this when the defaults pass it in, otherwise it should
// stay as `undefined` so that it falls back to the default in the key manager.
if ((_defaultOptions === null || _defaultOptions === void 0 ? void 0 : _defaultOptions.typeaheadDebounceInterval) != null) {
_this._typeaheadDebounceInterval = _defaultOptions.typeaheadDebounceInterval;
}
_this._scrollStrategyFactory = scrollStrategyFactory;
_this._scrollStrategy = _this._scrollStrategyFactory();
_this.tabIndex = parseInt(tabIndex) || 0;
// Force setter to be called in case id was not specified.
_this.id = _this.id;
return _this;
}
Object.defineProperty(_MatSelectBase.prototype, "focused", {
/** Whether the select is focused. */
get: function () {
return this._focused || this._panelOpen;
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "placeholder", {
/** Placeholder to be shown if no value has been selected. */
get: function () { return this._placeholder; },
set: function (value) {
this._placeholder = value;
this.stateChanges.next();
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "required", {
/** Whether the component is required. */
get: function () { return this._required; },
set: function (value) {
this._required = coercion.coerceBooleanProperty(value);
this.stateChanges.next();
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "multiple", {
/** Whether the user should be allowed to select multiple options. */
get: function () { return this._multiple; },
set: function (value) {
if (this._selectionModel && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw getMatSelectDynamicMultipleError();
}
this._multiple = coercion.coerceBooleanProperty(value);
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "disableOptionCentering", {
/** Whether to center the active option over the trigger. */
get: function () { return this._disableOptionCentering; },
set: function (value) {
this._disableOptionCentering = coercion.coerceBooleanProperty(value);
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "compareWith", {
/**
* Function to compare the option values with the selected values. The first argument
* is a value from an option. The second is a value from the selection. A boolean
* should be returned.
*/
get: function () { return this._compareWith; },
set: function (fn) {
if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw getMatSelectNonFunctionValueError();
}
this._compareWith = fn;
if (this._selectionModel) {
// A different comparator means the selection could change.
this._initializeSelection();
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "value", {
/** Value of the select control. */
get: function () { return this._value; },
set: function (newValue) {
// Always re-assign an array, because it might have been mutated.
if (newValue !== this._value || (this._multiple && Array.isArray(newValue))) {
if (this.options) {
this._setSelectionByValue(newValue);
}
this._value = newValue;
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "typeaheadDebounceInterval", {
/** Time to wait in milliseconds after the last keystroke before moving focus to an item. */
get: function () { return this._typeaheadDebounceInterval; },
set: function (value) {
this._typeaheadDebounceInterval = coercion.coerceNumberProperty(value);
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "id", {
/** Unique id of the element. */
get: function () { return this._id; },
set: function (value) {
this._id = value || this._uid;
this.stateChanges.next();
},
enumerable: false,
configurable: true
});
_MatSelectBase.prototype.ngOnInit = function () {
var _this = this;
this._selectionModel = new collections.SelectionModel(this.multiple);
this.stateChanges.next();
// We need `distinctUntilChanged` here, because some browsers will
// fire the animation end event twice for the same animation. See:
// https://github.com/angular/angular/issues/24084
this._panelDoneAnimatingStream
.pipe(operators.distinctUntilChanged(), operators.takeUntil(this._destroy))
.subscribe(function () { return _this._panelDoneAnimating(_this.panelOpen); });
};
_MatSelectBase.prototype.ngAfterContentInit = function () {
var _this = this;
this._initKeyManager();
this._selectionModel.changed.pipe(operators.takeUntil(this._destroy)).subscribe(function (event) {
event.added.forEach(function (option) { return option.select(); });
event.removed.forEach(function (option) { return option.deselect(); });
});
this.options.changes.pipe(operators.startWith(null), operators.takeUntil(this._destroy)).subscribe(function () {
_this._resetOptions();
_this._initializeSelection();
});
};
_MatSelectBase.prototype.ngDoCheck = function () {
var newAriaLabelledby = this._getTriggerAriaLabelledby();
// We have to manage setting the `aria-labelledby` ourselves, because part of its value
// is computed as a result of a content query which can cause this binding to trigger a
// "changed after checked" error.
if (newAriaLabelledby !== this._triggerAriaLabelledBy) {
var element = this._elementRef.nativeElement;
this._triggerAriaLabelledBy = newAriaLabelledby;
if (newAriaLabelledby) {
element.setAttribute('aria-labelledby', newAriaLabelledby);
}
else {
element.removeAttribute('aria-labelledby');
}
}
if (this.ngControl) {
this.updateErrorState();
}
};
_MatSelectBase.prototype.ngOnChanges = function (changes) {
// Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let
// the parent form field know to run change detection when the disabled state changes.
if (changes['disabled']) {
this.stateChanges.next();
}
if (changes['typeaheadDebounceInterval'] && this._keyManager) {
this._keyManager.withTypeAhead(this._typeaheadDebounceInterval);
}
};
_MatSelectBase.prototype.ngOnDestroy = function () {
this._destroy.next();
this._destroy.complete();
this.stateChanges.complete();
};
/** Toggles the overlay panel open or closed. */
_MatSelectBase.prototype.toggle = function () {
this.panelOpen ? this.close() : this.open();
};
/** Opens the overlay panel. */
_MatSelectBase.prototype.open = function () {
if (this._canOpen()) {
this._panelOpen = true;
this._keyManager.withHorizontalOrientation(null);
this._highlightCorrectOption();
this._changeDetectorRef.markForCheck();
}
};
/** Closes the overlay panel and focuses the host element. */
_MatSelectBase.prototype.close = function () {
if (this._panelOpen) {
this._panelOpen = false;
this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');
this._changeDetectorRef.markForCheck();
this._onTouched();
}
};
/**
* Sets the select's value. Part of the ControlValueAccessor interface
* required to integrate with Angular's core forms API.
*
* @param value New value to be written to the model.
*/
_MatSelectBase.prototype.writeValue = function (value) {
this.value = value;
};
/**
* Saves a callback function to be invoked when the select's value
* changes from user input. Part of the ControlValueAccessor interface
* required to integrate with Angular's core forms API.
*
* @param fn Callback to be triggered when the value changes.
*/
_MatSelectBase.prototype.registerOnChange = function (fn) {
this._onChange = fn;
};
/**
* Saves a callback function to be invoked when the select is blurred
* by the user. Part of the ControlValueAccessor interface required
* to integrate with Angular's core forms API.
*
* @param fn Callback to be triggered when the component has been touched.
*/
_MatSelectBase.prototype.registerOnTouched = function (fn) {
this._onTouched = fn;
};
/**
* Disables the select. Part of the ControlValueAccessor interface required
* to integrate with Angular's core forms API.
*
* @param isDisabled Sets whether the component is disabled.
*/
_MatSelectBase.prototype.setDisabledState = function (isDisabled) {
this.disabled = isDisabled;
this._changeDetectorRef.markForCheck();
this.stateChanges.next();
};
Object.defineProperty(_MatSelectBase.prototype, "panelOpen", {
/** Whether or not the overlay panel is open. */
get: function () {
return this._panelOpen;
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "selected", {
/** The currently selected option. */
get: function () {
return this.multiple ? this._selectionModel.selected : this._selectionModel.selected[0];
},
enumerable: false,
configurable: true
});
Object.defineProperty(_MatSelectBase.prototype, "triggerValue", {
/** The value displayed in the trigger. */
get: function () {
if (this.empty) {
return '';
}
if (this._multiple) {
var selectedOptions = this._selectionModel.selected.map(function (option) { return option.viewValue; });
if (this._isRtl()) {
selectedOptions.reverse();
}
// TODO(crisbeto): delimiter should be configurable for proper localization.
return selectedOptions.join(', ');
}
return this._selectionModel.selected[0].viewValue;
},
enumerable: false,
configurable: true
});
/** Whether the element is in RTL mode. */
_MatSelectBase.prototype._isRtl = function () {
return this._dir ? this._dir.value === 'rtl' : false;
};
/** Handles all keydown events on the select. */
_MatSelectBase.prototype._handleKeydown = function (event) {
if (!this.disabled) {
this.panelOpen ? this._handleOpenKeydown(event) : this._handleClosedKeydown(event);
}
};
/** Handles keyboard events while the select is closed. */
_MatSelectBase.prototype._handleClosedKeydown = function (event) {
var keyCode = event.keyCode;
var isArrowKey = keyCode === keycodes.DOWN_ARROW || keyCode === keycodes.UP_ARROW ||
keyCode === keycodes.LEFT_ARROW || keyCode === keycodes.RIGHT_ARROW;
var isOpenKey = keyCode === keycodes.ENTER || keyCode === keycodes.SPACE;
var manager = this._keyManager;
// Open the select on ALT + arrow key to match the native <select>
if (!manager.isTyping() && (isOpenKey && !keycodes.hasModifierKey(event)) ||
((this.multiple || event.altKey) && isArrowKey)) {
event.preventDefault(); // prevents the page from scrolling down when pressing space
this.open();
}
else if (!this.multiple) {
var previouslySelectedOption = this.selected;
manager.onKeydown(event);
var selectedOption = this.selected;
// Since the value has changed, we need to announce it ourselves.
if (selectedOption && previouslySelectedOption !== selectedOption) {
// We set a duration on the live announcement, because we want the live element to be
// cleared after a while so that users can't navigate to it using the arrow keys.
this._liveAnnouncer.announce(selectedOption.viewValue, 10000);
}
}
};
/** Handles keyboard events when the selected is open. */
_MatSelectBase.prototype._handleOpenKeydown = function (event) {
var manager = this._keyManager;
var keyCode = event.keyCode;
var isArrowKey = keyCode === keycodes.DOWN_ARROW || keyCode === keycodes.UP_ARROW;
var isTyping = manager.isTyping();
if (isArrowKey && event.altKey) {
// Close the select on ALT + arrow key to match the native <select>
event.preventDefault();
this.close();
// Don't do anything in this case if the user is typing,
// because the typing sequence can include the space key.
}
else if (!isTyping && (keyCode === keycodes.ENTER || keyCode === keycodes.SPACE) && manager.activeItem &&
!keycodes.hasModifierKey(event)) {
event.preventDefault();
manager.activeItem._selectViaInteraction();
}
else if (!isTyping && this._multiple && keyCode === keycodes.A && event.ctrlKey) {
event.preventDefault();
var hasDeselectedOptions_1 = this.options.some(function (opt) { return !opt.disabled && !opt.selected; });
this.options.forEach(function (option) {
if (!option.disabled) {
hasDeselectedOptions_1 ? option.select() : option.deselect();
}
});
}
else {
var previouslyFocusedIndex = manager.activeItemIndex;
manager.onKeydown(event);
if (this._multiple && isArrowKey && event.shiftKey && manager.activeItem &&
manager.activeItemIndex !== previouslyFocusedIndex) {
manager.activeItem._selectViaInteraction();
}
}
};
_MatSelectBase.prototype._onFocus = function () {
if (!this.disabled) {
this._focused = true;
this.stateChanges.next();
}
};
/**
* Calls the touched callback only if the panel is closed. Otherwise, the trigger will
* "blur" to the panel when it opens, causing a false positive.
*/
_MatSelectBase.prototype._onBlur = function () {
this._focused = false;
if (!this.disabled && !this.panelOpen) {
this._onTouched();
this._changeDetectorRef.markForCheck();
this.stateChanges.next();
}
};
/**
* Callback that is invoked when the overlay panel has been attached.
*/
_MatSelectBase.prototype._onAttached = function () {
var _this = this;
this.overlayDir.positionChange.pipe(operators.take(1)).subscribe(function () {
_this._changeDetectorRef.detectChanges();
_this._positioningSettled();
});
};
/** Returns the theme to be used on the panel. */
_MatSelectBase.prototype._getPanelTheme = function () {
return this._parentFormField ? "mat-" + this._parentFormField.color : '';
};
Object.defineProperty(_MatSelectBase.prototype, "empty", {
/** Whether the select has a value. */
get: function () {
return !this._selectionModel || this._selectionModel.isEmpty();
},
enumerable: false,
configurable: true
});
_MatSelectBase.prototype._initializeSelection = function () {
var _this = this;
// Defer setting the value in order to avoid the "Expression
// has changed after it was checked" errors from Angular.
Promise.resolve().then(function () {
_this._setSelectionByValue(_this.ngControl ? _this.ngControl.value : _this._value);
_this.stateChanges.next();
});
};
/**
* Sets the selected option based on a value. If no option can be
* found with the designated value, the select trigger is cleared.
*/
_MatSelectBase.prototype._setSelectionByValue = function (value) {
var _this = this;
this._selectionModel.selected.forEach(function (option) { return option.setInactiveStyles(); });
this._selectionModel.clear();
if (this.multiple && value) {
if (!Array.isArray(value) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw getMatSelectNonArrayValueError();
}
value.forEach(function (currentValue) { return _this._selectValue(currentValue); });
this._sortValues();
}
else {
var correspondingOption = this._selectValue(value);
// Shift focus to the active item. Note that we shouldn't do this in multiple
// mode, because we don't know what option the user interacted with last.
if (correspondingOption) {
this._keyManager.updateActiveItem(correspondingOption);
}
else if (!this.panelOpen) {
// Otherwise reset the highlighted option. Note that we only want to do this while
// closed, because doing it while open can shift the user's focus unnecessarily.
this._keyManager.updateActiveItem(-1);
}
}
this._changeDetectorRef.markForCheck();
};
/**
* Finds and selects and option based on its value.
* @returns Option that has the corresponding value.
*/
_MatSelectBase.prototype._selectValue = function (value) {
var _this = this;
var correspondingOption = this.options.find(function (option) {
// Skip options that are already in the model. This allows us to handle cases
// where the same primitive value is selected multiple times.
if (_this._selectionModel.isSelected(option)) {
return false;
}
try {
// Treat null as a special reset value.
return option.value != null && _this._compareWith(option.value, value);
}
catch (error) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
// Notify developers of errors in their comparator.
console.warn(error);
}
return false;
}
});
if (correspondingOption) {
this._selectionModel.select(correspondingOption);
}
return correspondingOption;
};
/** Sets up a key manager to listen to keyboard events on the overlay panel. */
_MatSelectBase.prototype._initKeyManager = function () {
var _this = this;
this._keyManager = new a11y.ActiveDescendantKeyManager(this.options)
.withTypeAhead(this._typeaheadDebounceInterval)
.withVerticalOrientation()
.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')
.withHomeAndEnd()
.wit