/** * @license Angular v5.2.11 * (c) 2010-2018 Google, Inc. https://angular.io/ * License: MIT */ import { Directive, ElementRef, EventEmitter, Host, Inject, Injectable, InjectionToken, Injector, Input, NgModule, Optional, Output, Renderer2, Self, SkipSelf, Version, forwardRef, ɵisObservable, ɵisPromise, ɵlooseIdentical } from '@angular/core'; import { forkJoin } from 'rxjs/observable/forkJoin'; import { fromPromise } from 'rxjs/observable/fromPromise'; import { map } from 'rxjs/operator/map'; import { ɵgetDOM } from '@angular/platform-browser'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * Base class for control directives. * * Only used internally in the forms module. * * \@stable * @abstract */ class AbstractControlDirective { /** * The value of the control. * @return {?} */ get value() { return this.control ? this.control.value : null; } /** * A control is `valid` when its `status === VALID`. * * In order to have this status, the control must have passed all its * validation checks. * @return {?} */ get valid() { return this.control ? this.control.valid : null; } /** * A control is `invalid` when its `status === INVALID`. * * In order to have this status, the control must have failed * at least one of its validation checks. * @return {?} */ get invalid() { return this.control ? this.control.invalid : null; } /** * A control is `pending` when its `status === PENDING`. * * In order to have this status, the control must be in the * middle of conducting a validation check. * @return {?} */ get pending() { return this.control ? this.control.pending : null; } /** * A control is `disabled` when its `status === DISABLED`. * * Disabled controls are exempt from validation checks and * are not included in the aggregate value of their ancestor * controls. * @return {?} */ get disabled() { return this.control ? this.control.disabled : null; } /** * A control is `enabled` as long as its `status !== DISABLED`. * * In other words, it has a status of `VALID`, `INVALID`, or * `PENDING`. * @return {?} */ get enabled() { return this.control ? this.control.enabled : null; } /** * Returns any errors generated by failing validation. If there * are no errors, it will return null. * @return {?} */ get errors() { return this.control ? this.control.errors : null; } /** * A control is `pristine` if the user has not yet changed * the value in the UI. * * Note that programmatic changes to a control's value will * *not* mark it dirty. * @return {?} */ get pristine() { return this.control ? this.control.pristine : null; } /** * A control is `dirty` if the user has changed the value * in the UI. * * Note that programmatic changes to a control's value will * *not* mark it dirty. * @return {?} */ get dirty() { return this.control ? this.control.dirty : null; } /** * A control is marked `touched` once the user has triggered * a `blur` event on it. * @return {?} */ get touched() { return this.control ? this.control.touched : null; } /** * @return {?} */ get status() { return this.control ? this.control.status : null; } /** * A control is `untouched` if the user has not yet triggered * a `blur` event on it. * @return {?} */ get untouched() { return this.control ? this.control.untouched : null; } /** * Emits an event every time the validation status of the control * is re-calculated. * @return {?} */ get statusChanges() { return this.control ? this.control.statusChanges : null; } /** * Emits an event every time the value of the control changes, in * the UI or programmatically. * @return {?} */ get valueChanges() { return this.control ? this.control.valueChanges : null; } /** * Returns an array that represents the path from the top-level form * to this control. Each index is the string name of the control on * that level. * @return {?} */ get path() { return null; } /** * Resets the form control. This means by default: * * * it is marked as `pristine` * * it is marked as `untouched` * * value is set to null * * For more information, see {\@link AbstractControl}. * @param {?=} value * @return {?} */ reset(value = undefined) { if (this.control) this.control.reset(value); } /** * Returns true if the control with the given path has the error specified. Otherwise * returns false. * * If no path is given, it checks for the error on the present control. * @param {?} errorCode * @param {?=} path * @return {?} */ hasError(errorCode, path) { return this.control ? this.control.hasError(errorCode, path) : false; } /** * Returns error data if the control with the given path has the error specified. Otherwise * returns null or undefined. * * If no path is given, it checks for the error on the present control. * @param {?} errorCode * @param {?=} path * @return {?} */ getError(errorCode, path) { return this.control ? this.control.getError(errorCode, path) : null; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * A directive that contains multiple {\@link NgControl}s. * * Only used by the forms module. * * \@stable * @abstract */ class ControlContainer extends AbstractControlDirective { /** * Get the form to which this container belongs. * @return {?} */ get formDirective() { return null; } /** * Get the path to this container. * @return {?} */ get path() { return null; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * @param {?} value * @return {?} */ function isEmptyInputValue(value) { // we don't check for string here so it also works with arrays return value == null || value.length === 0; } /** * Providers for validators to be used for {\@link FormControl}s in a form. * * Provide this using `multi: true` to add validators. * * ### Example * * ```typescript * \@Directive({ * selector: '[custom-validator]', * providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}] * }) * class CustomValidatorDirective implements Validator { * validate(control: AbstractControl): ValidationErrors | null { * return {"custom": true}; * } * } * ``` * * \@stable */ const NG_VALIDATORS = new InjectionToken('NgValidators'); /** * Providers for asynchronous validators to be used for {\@link FormControl}s * in a form. * * Provide this using `multi: true` to add validators. * * See {\@link NG_VALIDATORS} for more details. * * \@stable */ const NG_ASYNC_VALIDATORS = new InjectionToken('NgAsyncValidators'); const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; /** * Provides a set of validators used by form controls. * * A validator is a function that processes a {\@link FormControl} or collection of * controls and returns a map of errors. A null map means that validation has passed. * * ### Example * * ```typescript * var loginControl = new FormControl("", Validators.required) * ``` * * \@stable */ class Validators { /** * Validator that requires controls to have a value greater than a number. * `min()` exists only as a function, not as a directive. For example, * `control = new FormControl('', Validators.min(3));`. * @param {?} min * @return {?} */ static min(min) { return (control) => { if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) { return null; // don't validate empty values to allow optional controls } const /** @type {?} */ value = parseFloat(control.value); // Controls with NaN values after parsing should be treated as not having a // minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min return !isNaN(value) && value < min ? { 'min': { 'min': min, 'actual': control.value } } : null; }; } /** * Validator that requires controls to have a value less than a number. * `max()` exists only as a function, not as a directive. For example, * `control = new FormControl('', Validators.max(15));`. * @param {?} max * @return {?} */ static max(max) { return (control) => { if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) { return null; // don't validate empty values to allow optional controls } const /** @type {?} */ value = parseFloat(control.value); // Controls with NaN values after parsing should be treated as not having a // maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max return !isNaN(value) && value > max ? { 'max': { 'max': max, 'actual': control.value } } : null; }; } /** * Validator that requires controls to have a non-empty value. * @param {?} control * @return {?} */ static required(control) { return isEmptyInputValue(control.value) ? { 'required': true } : null; } /** * Validator that requires control value to be true. * @param {?} control * @return {?} */ static requiredTrue(control) { return control.value === true ? null : { 'required': true }; } /** * Validator that performs email validation. * @param {?} control * @return {?} */ static email(control) { return EMAIL_REGEXP.test(control.value) ? null : { 'email': true }; } /** * Validator that requires controls to have a value of a minimum length. * @param {?} minLength * @return {?} */ static minLength(minLength) { return (control) => { if (isEmptyInputValue(control.value)) { return null; // don't validate empty values to allow optional controls } const /** @type {?} */ length = control.value ? control.value.length : 0; return length < minLength ? { 'minlength': { 'requiredLength': minLength, 'actualLength': length } } : null; }; } /** * Validator that requires controls to have a value of a maximum length. * @param {?} maxLength * @return {?} */ static maxLength(maxLength) { return (control) => { const /** @type {?} */ length = control.value ? control.value.length : 0; return length > maxLength ? { 'maxlength': { 'requiredLength': maxLength, 'actualLength': length } } : null; }; } /** * Validator that requires a control to match a regex to its value. * @param {?} pattern * @return {?} */ static pattern(pattern) { if (!pattern) return Validators.nullValidator; let /** @type {?} */ regex; let /** @type {?} */ regexStr; if (typeof pattern === 'string') { regexStr = ''; if (pattern.charAt(0) !== '^') regexStr += '^'; regexStr += pattern; if (pattern.charAt(pattern.length - 1) !== '$') regexStr += '$'; regex = new RegExp(regexStr); } else { regexStr = pattern.toString(); regex = pattern; } return (control) => { if (isEmptyInputValue(control.value)) { return null; // don't validate empty values to allow optional controls } const /** @type {?} */ value = control.value; return regex.test(value) ? null : { 'pattern': { 'requiredPattern': regexStr, 'actualValue': value } }; }; } /** * No-op validator. * @param {?} c * @return {?} */ static nullValidator(c) { return null; } /** * @param {?} validators * @return {?} */ static compose(validators) { if (!validators) return null; const /** @type {?} */ presentValidators = /** @type {?} */ (validators.filter(isPresent)); if (presentValidators.length == 0) return null; return function (control) { return _mergeErrors(_executeValidators(control, presentValidators)); }; } /** * @param {?} validators * @return {?} */ static composeAsync(validators) { if (!validators) return null; const /** @type {?} */ presentValidators = /** @type {?} */ (validators.filter(isPresent)); if (presentValidators.length == 0) return null; return function (control) { const /** @type {?} */ observables = _executeAsyncValidators(control, presentValidators).map(toObservable); return map.call(forkJoin(observables), _mergeErrors); }; } } /** * @param {?} o * @return {?} */ function isPresent(o) { return o != null; } /** * @param {?} r * @return {?} */ function toObservable(r) { const /** @type {?} */ obs = ɵisPromise(r) ? fromPromise(r) : r; if (!(ɵisObservable(obs))) { throw new Error(`Expected validator to return Promise or Observable.`); } return obs; } /** * @param {?} control * @param {?} validators * @return {?} */ function _executeValidators(control, validators) { return validators.map(v => v(control)); } /** * @param {?} control * @param {?} validators * @return {?} */ function _executeAsyncValidators(control, validators) { return validators.map(v => v(control)); } /** * @param {?} arrayOfErrors * @return {?} */ function _mergeErrors(arrayOfErrors) { const /** @type {?} */ res = arrayOfErrors.reduce((res, errors) => { return errors != null ? Object.assign({}, /** @type {?} */ ((res)), errors) : /** @type {?} */ ((res)); }, {}); return Object.keys(res).length === 0 ? null : res; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * A `ControlValueAccessor` acts as a bridge between the Angular forms API and a * native element in the DOM. * * Implement this interface if you want to create a custom form control directive * that integrates with Angular forms. * * \@stable * @record */ /** * Used to provide a {\@link ControlValueAccessor} for form controls. * * See {\@link DefaultValueAccessor} for how to implement one. * \@stable */ const NG_VALUE_ACCESSOR = new InjectionToken('NgValueAccessor'); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ const CHECKBOX_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CheckboxControlValueAccessor), multi: true, }; /** * The accessor for writing a value and listening to changes on a checkbox input element. * * ### Example * ``` * * ``` * * \@stable */ class CheckboxControlValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef */ constructor(_renderer, _elementRef) { this._renderer = _renderer; this._elementRef = _elementRef; this.onChange = (_) => { }; this.onTouched = () => { }; } /** * @param {?} value * @return {?} */ writeValue(value) { this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } } CheckboxControlValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]', host: { '(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()' }, providers: [CHECKBOX_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ CheckboxControlValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ const DEFAULT_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DefaultValueAccessor), multi: true }; /** * We must check whether the agent is Android because composition events * behave differently between iOS and Android. * @return {?} */ function _isAndroid() { const /** @type {?} */ userAgent = ɵgetDOM() ? ɵgetDOM().getUserAgent() : ''; return /android (\d+)/.test(userAgent.toLowerCase()); } /** * Turn this mode on if you want form directives to buffer IME input until compositionend * \@experimental */ const COMPOSITION_BUFFER_MODE = new InjectionToken('CompositionEventMode'); /** * The default accessor for writing a value and listening to changes that is used by the * {\@link NgModel}, {\@link FormControlDirective}, and {\@link FormControlName} directives. * * ### Example * ``` * * ``` * * \@stable */ class DefaultValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef * @param {?} _compositionMode */ constructor(_renderer, _elementRef, _compositionMode) { this._renderer = _renderer; this._elementRef = _elementRef; this._compositionMode = _compositionMode; this.onChange = (_) => { }; this.onTouched = () => { }; /** * Whether the user is creating a composition string (IME events). */ this._composing = false; if (this._compositionMode == null) { this._compositionMode = !_isAndroid(); } } /** * @param {?} value * @return {?} */ writeValue(value) { const /** @type {?} */ normalizedValue = value == null ? '' : value; this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } /** * \@internal * @param {?} value * @return {?} */ _handleInput(value) { if (!this._compositionMode || (this._compositionMode && !this._composing)) { this.onChange(value); } } /** * \@internal * @return {?} */ _compositionStart() { this._composing = true; } /** * \@internal * @param {?} value * @return {?} */ _compositionEnd(value) { this._composing = false; this._compositionMode && this.onChange(value); } } DefaultValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]', // TODO: vsavkin replace the above selector with the one below it once // https://github.com/angular/angular/issues/3011 is implemented // selector: '[ngModel],[formControl],[formControlName]', host: { '(input)': '$any(this)._handleInput($event.target.value)', '(blur)': 'onTouched()', '(compositionstart)': '$any(this)._compositionStart()', '(compositionend)': '$any(this)._compositionEnd($event.target.value)' }, providers: [DEFAULT_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ DefaultValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [COMPOSITION_BUFFER_MODE,] },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * @param {?} validator * @return {?} */ function normalizeValidator(validator) { if ((/** @type {?} */ (validator)).validate) { return (c) => (/** @type {?} */ (validator)).validate(c); } else { return /** @type {?} */ (validator); } } /** * @param {?} validator * @return {?} */ function normalizeAsyncValidator(validator) { if ((/** @type {?} */ (validator)).validate) { return (c) => (/** @type {?} */ (validator)).validate(c); } else { return /** @type {?} */ (validator); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ const NUMBER_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NumberValueAccessor), multi: true }; /** * The accessor for writing a number value and listening to changes that is used by the * {\@link NgModel}, {\@link FormControlDirective}, and {\@link FormControlName} directives. * * ### Example * ``` * * ``` */ class NumberValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef */ constructor(_renderer, _elementRef) { this._renderer = _renderer; this._elementRef = _elementRef; this.onChange = (_) => { }; this.onTouched = () => { }; } /** * @param {?} value * @return {?} */ writeValue(value) { // The value needs to be normalized for IE9, otherwise it is set to 'null' when null const /** @type {?} */ normalizedValue = value == null ? '' : value; this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); }; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } } NumberValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]', host: { '(change)': 'onChange($event.target.value)', '(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()' }, providers: [NUMBER_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ NumberValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * @return {?} */ function unimplemented() { throw new Error('unimplemented'); } /** * A base class that all control directive extend. * It binds a {\@link FormControl} object to a DOM element. * * Used internally by Angular forms. * * \@stable * @abstract */ class NgControl extends AbstractControlDirective { constructor() { super(...arguments); /** * \@internal */ this._parent = null; this.name = null; this.valueAccessor = null; /** * \@internal */ this._rawValidators = []; /** * \@internal */ this._rawAsyncValidators = []; } /** * @return {?} */ get validator() { return /** @type {?} */ (unimplemented()); } /** * @return {?} */ get asyncValidator() { return /** @type {?} */ (unimplemented()); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ const RADIO_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RadioControlValueAccessor), multi: true }; /** * Internal class used by Angular to uncheck radio buttons with the matching name. */ class RadioControlRegistry { constructor() { this._accessors = []; } /** * @param {?} control * @param {?} accessor * @return {?} */ add(control, accessor) { this._accessors.push([control, accessor]); } /** * @param {?} accessor * @return {?} */ remove(accessor) { for (let /** @type {?} */ i = this._accessors.length - 1; i >= 0; --i) { if (this._accessors[i][1] === accessor) { this._accessors.splice(i, 1); return; } } } /** * @param {?} accessor * @return {?} */ select(accessor) { this._accessors.forEach((c) => { if (this._isSameGroup(c, accessor) && c[1] !== accessor) { c[1].fireUncheck(accessor.value); } }); } /** * @param {?} controlPair * @param {?} accessor * @return {?} */ _isSameGroup(controlPair, accessor) { if (!controlPair[0].control) return false; return controlPair[0]._parent === accessor._control._parent && controlPair[1].name === accessor.name; } } RadioControlRegistry.decorators = [ { type: Injectable }, ]; /** @nocollapse */ RadioControlRegistry.ctorParameters = () => []; /** * \@whatItDoes Writes radio control values and listens to radio control changes. * * Used by {\@link NgModel}, {\@link FormControlDirective}, and {\@link FormControlName} * to keep the view synced with the {\@link FormControl} model. * * \@howToUse * * If you have imported the {\@link FormsModule} or the {\@link ReactiveFormsModule}, this * value accessor will be active on any radio control that has a form directive. You do * **not** need to add a special selector to activate it. * * ### How to use radio buttons with form directives * * To use radio buttons in a template-driven form, you'll want to ensure that radio buttons * in the same group have the same `name` attribute. Radio buttons with different `name` * attributes do not affect each other. * * {\@example forms/ts/radioButtons/radio_button_example.ts region='TemplateDriven'} * * When using radio buttons in a reactive form, radio buttons in the same group should have the * same `formControlName`. You can also add a `name` attribute, but it's optional. * * {\@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'} * * * **npm package**: `\@angular/forms` * * \@stable */ class RadioControlValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef * @param {?} _registry * @param {?} _injector */ constructor(_renderer, _elementRef, _registry, _injector) { this._renderer = _renderer; this._elementRef = _elementRef; this._registry = _registry; this._injector = _injector; this.onChange = () => { }; this.onTouched = () => { }; } /** * @return {?} */ ngOnInit() { this._control = this._injector.get(NgControl); this._checkName(); this._registry.add(this._control, this); } /** * @return {?} */ ngOnDestroy() { this._registry.remove(this); } /** * @param {?} value * @return {?} */ writeValue(value) { this._state = value === this.value; this._renderer.setProperty(this._elementRef.nativeElement, 'checked', this._state); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this._fn = fn; this.onChange = () => { fn(this.value); this._registry.select(this); }; } /** * @param {?} value * @return {?} */ fireUncheck(value) { this.writeValue(value); } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } /** * @return {?} */ _checkName() { if (this.name && this.formControlName && this.name !== this.formControlName) { this._throwNameError(); } if (!this.name && this.formControlName) this.name = this.formControlName; } /** * @return {?} */ _throwNameError() { throw new Error(` If you define both a name and a formControlName attribute on your radio button, their values must match. Ex: `); } } RadioControlValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]', host: { '(change)': 'onChange()', '(blur)': 'onTouched()' }, providers: [RADIO_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ RadioControlValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, { type: RadioControlRegistry, }, { type: Injector, }, ]; RadioControlValueAccessor.propDecorators = { "name": [{ type: Input },], "formControlName": [{ type: Input },], "value": [{ type: Input },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ const RANGE_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RangeValueAccessor), multi: true }; /** * The accessor for writing a range value and listening to changes that is used by the * {\@link NgModel}, {\@link FormControlDirective}, and {\@link FormControlName} directives. * * ### Example * ``` * * ``` */ class RangeValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef */ constructor(_renderer, _elementRef) { this._renderer = _renderer; this._elementRef = _elementRef; this.onChange = (_) => { }; this.onTouched = () => { }; } /** * @param {?} value * @return {?} */ writeValue(value) { this._renderer.setProperty(this._elementRef.nativeElement, 'value', parseFloat(value)); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); }; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } } RangeValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]', host: { '(change)': 'onChange($event.target.value)', '(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()' }, providers: [RANGE_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ RangeValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ const SELECT_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectControlValueAccessor), multi: true }; /** * @param {?} id * @param {?} value * @return {?} */ function _buildValueString(id, value) { if (id == null) return `${value}`; if (value && typeof value === 'object') value = 'Object'; return `${id}: ${value}`.slice(0, 50); } /** * @param {?} valueString * @return {?} */ function _extractId(valueString) { return valueString.split(':')[0]; } /** * \@whatItDoes Writes values and listens to changes on a select element. * * Used by {\@link NgModel}, {\@link FormControlDirective}, and {\@link FormControlName} * to keep the view synced with the {\@link FormControl} model. * * \@howToUse * * If you have imported the {\@link FormsModule} or the {\@link ReactiveFormsModule}, this * value accessor will be active on any select control that has a form directive. You do * **not** need to add a special selector to activate it. * * ### How to use select controls with form directives * * To use a select in a template-driven form, simply add an `ngModel` and a `name` * attribute to the main `` tag. Like in the former example, you have the * choice of binding to the `value` or `ngValue` property on the select's options. * * {\@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'} * * ### Caveat: Option selection * * Angular uses object identity to select option. It's possible for the identities of items * to change while the data does not. This can happen, for example, if the items are produced * from an RPC to the server, and that RPC is re-run. Even if the data hasn't changed, the * second response will produce objects with different identities. * * To customize the default option comparison algorithm, ` * * * * compareFn(c1: Country, c2: Country): boolean { * return c1 && c2 ? c1.id === c2.id : c1 === c2; * } * ``` * * Note: We listen to the 'change' event because 'input' events aren't fired * for selects in Firefox and IE: * https://bugzilla.mozilla.org/show_bug.cgi?id=1024350 * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4660045/ * * * **npm package**: `\@angular/forms` * * \@stable */ class SelectControlValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef */ constructor(_renderer, _elementRef) { this._renderer = _renderer; this._elementRef = _elementRef; /** * \@internal */ this._optionMap = new Map(); /** * \@internal */ this._idCounter = 0; this.onChange = (_) => { }; this.onTouched = () => { }; this._compareWith = ɵlooseIdentical; } /** * @param {?} fn * @return {?} */ set compareWith(fn) { if (typeof fn !== 'function') { throw new Error(`compareWith must be a function, but received ${JSON.stringify(fn)}`); } this._compareWith = fn; } /** * @param {?} value * @return {?} */ writeValue(value) { this.value = value; const /** @type {?} */ id = this._getOptionId(value); if (id == null) { this._renderer.setProperty(this._elementRef.nativeElement, 'selectedIndex', -1); } const /** @type {?} */ valueString = _buildValueString(id, value); this._renderer.setProperty(this._elementRef.nativeElement, 'value', valueString); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = (valueString) => { this.value = this._getOptionValue(valueString); fn(this.value); }; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } /** * \@internal * @return {?} */ _registerOption() { return (this._idCounter++).toString(); } /** * \@internal * @param {?} value * @return {?} */ _getOptionId(value) { for (const /** @type {?} */ id of Array.from(this._optionMap.keys())) { if (this._compareWith(this._optionMap.get(id), value)) return id; } return null; } /** * \@internal * @param {?} valueString * @return {?} */ _getOptionValue(valueString) { const /** @type {?} */ id = _extractId(valueString); return this._optionMap.has(id) ? this._optionMap.get(id) : valueString; } } SelectControlValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]', host: { '(change)': 'onChange($event.target.value)', '(blur)': 'onTouched()' }, providers: [SELECT_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ SelectControlValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, ]; SelectControlValueAccessor.propDecorators = { "compareWith": [{ type: Input },], }; /** * \@whatItDoes Marks ` * * * compareFn(c1: Country, c2: Country): boolean { * return c1 && c2 ? c1.id === c2.id : c1 === c2; * } * ``` * * \@stable */ class SelectMultipleControlValueAccessor { /** * @param {?} _renderer * @param {?} _elementRef */ constructor(_renderer, _elementRef) { this._renderer = _renderer; this._elementRef = _elementRef; /** * \@internal */ this._optionMap = new Map(); /** * \@internal */ this._idCounter = 0; this.onChange = (_) => { }; this.onTouched = () => { }; this._compareWith = ɵlooseIdentical; } /** * @param {?} fn * @return {?} */ set compareWith(fn) { if (typeof fn !== 'function') { throw new Error(`compareWith must be a function, but received ${JSON.stringify(fn)}`); } this._compareWith = fn; } /** * @param {?} value * @return {?} */ writeValue(value) { this.value = value; let /** @type {?} */ optionSelectedStateSetter; if (Array.isArray(value)) { // convert values to ids const /** @type {?} */ ids = value.map((v) => this._getOptionId(v)); optionSelectedStateSetter = (opt, o) => { opt._setSelected(ids.indexOf(o.toString()) > -1); }; } else { optionSelectedStateSetter = (opt, o) => { opt._setSelected(false); }; } this._optionMap.forEach(optionSelectedStateSetter); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChange = (_) => { const /** @type {?} */ selected = []; if (_.hasOwnProperty('selectedOptions')) { const /** @type {?} */ options = _.selectedOptions; for (let /** @type {?} */ i = 0; i < options.length; i++) { const /** @type {?} */ opt = options.item(i); const /** @type {?} */ val = this._getOptionValue(opt.value); selected.push(val); } } else { const /** @type {?} */ options = /** @type {?} */ (_.options); for (let /** @type {?} */ i = 0; i < options.length; i++) { const /** @type {?} */ opt = options.item(i); if (opt.selected) { const /** @type {?} */ val = this._getOptionValue(opt.value); selected.push(val); } } } this.value = selected; fn(selected); }; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouched = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled); } /** * \@internal * @param {?} value * @return {?} */ _registerOption(value) { const /** @type {?} */ id = (this._idCounter++).toString(); this._optionMap.set(id, value); return id; } /** * \@internal * @param {?} value * @return {?} */ _getOptionId(value) { for (const /** @type {?} */ id of Array.from(this._optionMap.keys())) { if (this._compareWith(/** @type {?} */ ((this._optionMap.get(id)))._value, value)) return id; } return null; } /** * \@internal * @param {?} valueString * @return {?} */ _getOptionValue(valueString) { const /** @type {?} */ id = _extractId$1(valueString); return this._optionMap.has(id) ? /** @type {?} */ ((this._optionMap.get(id)))._value : valueString; } } SelectMultipleControlValueAccessor.decorators = [ { type: Directive, args: [{ selector: 'select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]', host: { '(change)': 'onChange($event.target)', '(blur)': 'onTouched()' }, providers: [SELECT_MULTIPLE_VALUE_ACCESSOR] },] }, ]; /** @nocollapse */ SelectMultipleControlValueAccessor.ctorParameters = () => [ { type: Renderer2, }, { type: ElementRef, }, ]; SelectMultipleControlValueAccessor.propDecorators = { "compareWith": [{ type: Input },], }; /** * Marks `