/**
* @license Angular v8.1.0
* (c) 2010-2019 Google LLC. https://angular.io/
* License: MIT
*/
import { __decorate, __metadata, __param, __extends, __assign, __values, __spread } from 'tslib';
import { InjectionToken, forwardRef, Directive, Renderer2, ElementRef, Optional, Inject, Self, ɵisPromise, ɵisObservable, Injectable, Input, Injector, Host, ɵlooseIdentical, isDevMode, EventEmitter, SkipSelf, Output, NgModule, Version } from '@angular/core';
import { ɵgetDOM } from '@angular/platform-browser';
import { forkJoin, from } from 'rxjs';
import { map } from 'rxjs/operators';
/**
* @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
*/
/**
* Used to provide a `ControlValueAccessor` for form controls.
*
* See `DefaultValueAccessor` for how to implement one.
*
* @publicApi
*/
var NG_VALUE_ACCESSOR = new InjectionToken('NgValueAccessor');
/**
* @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
*/
var CHECKBOX_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return CheckboxControlValueAccessor; }),
multi: true,
};
/**
* @description
* A `ControlValueAccessor` for writing a value and listening to changes on a checkbox input
* element.
*
* @usageNotes
*
* ### Using a checkbox with a reactive form.
*
* The following example shows how to use a checkbox with a reactive form.
*
* ```ts
* const rememberLoginControl = new FormControl();
* ```
*
* ```
*
* ```
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var CheckboxControlValueAccessor = /** @class */ (function () {
function CheckboxControlValueAccessor(_renderer, _elementRef) {
this._renderer = _renderer;
this._elementRef = _elementRef;
/**
* @description
* The registered callback function called when a change event occurs on the input element.
*/
this.onChange = function (_) { };
/**
* @description
* The registered callback function called when a blur event occurs on the input element.
*/
this.onTouched = function () { };
}
/**
* Sets the "checked" property on the input element.
*
* @param value The checked value
*/
CheckboxControlValueAccessor.prototype.writeValue = function (value) {
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value);
};
/**
* @description
* Registers a function called when the control value changes.
*
* @param fn The callback function
*/
CheckboxControlValueAccessor.prototype.registerOnChange = function (fn) { this.onChange = fn; };
/**
* @description
* Registers a function called when the control is touched.
*
* @param fn The callback function
*/
CheckboxControlValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };
/**
* Sets the "disabled" property on the input element.
*
* @param isDisabled The disabled value
*/
CheckboxControlValueAccessor.prototype.setDisabledState = function (isDisabled) {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
};
CheckboxControlValueAccessor = __decorate([
Directive({
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]
}),
__metadata("design:paramtypes", [Renderer2, ElementRef])
], CheckboxControlValueAccessor);
return CheckboxControlValueAccessor;
}());
/**
* @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
*/
var DEFAULT_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return DefaultValueAccessor; }),
multi: true
};
/**
* We must check whether the agent is Android because composition events
* behave differently between iOS and Android.
*/
function _isAndroid() {
var userAgent = ɵgetDOM() ? ɵgetDOM().getUserAgent() : '';
return /android (\d+)/.test(userAgent.toLowerCase());
}
/**
* @description
* Provide this token to control if form directives buffer IME input until
* the "compositionend" event occurs.
* @publicApi
*/
var COMPOSITION_BUFFER_MODE = new InjectionToken('CompositionEventMode');
/**
* @description
* The default `ControlValueAccessor` for writing a value and listening to changes on input
* elements. The accessor is used by the `FormControlDirective`, `FormControlName`, and
* `NgModel` directives.
*
* @usageNotes
*
* ### Using the default value accessor
*
* The following example shows how to use an input element that activates the default value accessor
* (in this case, a text field).
*
* ```ts
* const firstNameControl = new FormControl();
* ```
*
* ```
*
* ```
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var DefaultValueAccessor = /** @class */ (function () {
function DefaultValueAccessor(_renderer, _elementRef, _compositionMode) {
this._renderer = _renderer;
this._elementRef = _elementRef;
this._compositionMode = _compositionMode;
/**
* @description
* The registered callback function called when an input event occurs on the input element.
*/
this.onChange = function (_) { };
/**
* @description
* The registered callback function called when a blur event occurs on the input element.
*/
this.onTouched = function () { };
/** Whether the user is creating a composition string (IME events). */
this._composing = false;
if (this._compositionMode == null) {
this._compositionMode = !_isAndroid();
}
}
/**
* Sets the "value" property on the input element.
*
* @param value The checked value
*/
DefaultValueAccessor.prototype.writeValue = function (value) {
var normalizedValue = value == null ? '' : value;
this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
};
/**
* @description
* Registers a function called when the control value changes.
*
* @param fn The callback function
*/
DefaultValueAccessor.prototype.registerOnChange = function (fn) { this.onChange = fn; };
/**
* @description
* Registers a function called when the control is touched.
*
* @param fn The callback function
*/
DefaultValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };
/**
* Sets the "disabled" property on the input element.
*
* @param isDisabled The disabled value
*/
DefaultValueAccessor.prototype.setDisabledState = function (isDisabled) {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
};
/** @internal */
DefaultValueAccessor.prototype._handleInput = function (value) {
if (!this._compositionMode || (this._compositionMode && !this._composing)) {
this.onChange(value);
}
};
/** @internal */
DefaultValueAccessor.prototype._compositionStart = function () { this._composing = true; };
/** @internal */
DefaultValueAccessor.prototype._compositionEnd = function (value) {
this._composing = false;
this._compositionMode && this.onChange(value);
};
DefaultValueAccessor = __decorate([
Directive({
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]
}),
__param(2, Optional()), __param(2, Inject(COMPOSITION_BUFFER_MODE)),
__metadata("design:paramtypes", [Renderer2, ElementRef, Boolean])
], DefaultValueAccessor);
return DefaultValueAccessor;
}());
/**
* @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
*/
/**
* @description
* Base class for control directives.
*
* This class is only used internally in the `ReactiveFormsModule` and the `FormsModule`.
*
* @publicApi
*/
var AbstractControlDirective = /** @class */ (function () {
function AbstractControlDirective() {
}
Object.defineProperty(AbstractControlDirective.prototype, "value", {
/**
* @description
* Reports the value of the control if it is present, otherwise null.
*/
get: function () { return this.control ? this.control.value : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "valid", {
/**
* @description
* Reports whether the control is valid. A control is considered valid if no
* validation errors exist with the current value.
* If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.valid : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "invalid", {
/**
* @description
* Reports whether the control is invalid, meaning that an error exists in the input value.
* If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.invalid : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "pending", {
/**
* @description
* Reports whether a control is pending, meaning that that async validation is occurring and
* errors are not yet available for the input value. If the control is not present, null is
* returned.
*/
get: function () { return this.control ? this.control.pending : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "disabled", {
/**
* @description
* Reports whether the control is disabled, meaning that the control is disabled
* in the UI and is exempt from validation checks and excluded from aggregate
* values of ancestor controls. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.disabled : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "enabled", {
/**
* @description
* Reports whether the control is enabled, meaning that the control is included in ancestor
* calculations of validity or value. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.enabled : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "errors", {
/**
* @description
* Reports the control's validation errors. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.errors : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "pristine", {
/**
* @description
* Reports whether the control is pristine, meaning that the user has not yet changed
* the value in the UI. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.pristine : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "dirty", {
/**
* @description
* Reports whether the control is dirty, meaning that the user has changed
* the value in the UI. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.dirty : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "touched", {
/**
* @description
* Reports whether the control is touched, meaning that the user has triggered
* a `blur` event on it. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.touched : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "status", {
/**
* @description
* Reports the validation status of the control. Possible values include:
* 'VALID', 'INVALID', 'DISABLED', and 'PENDING'.
* If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.status : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "untouched", {
/**
* @description
* Reports whether the control is untouched, meaning that the user has not yet triggered
* a `blur` event on it. If the control is not present, null is returned.
*/
get: function () { return this.control ? this.control.untouched : null; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "statusChanges", {
/**
* @description
* Returns a multicasting observable that emits a validation status whenever it is
* calculated for the control. If the control is not present, null is returned.
*/
get: function () {
return this.control ? this.control.statusChanges : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "valueChanges", {
/**
* @description
* Returns a multicasting observable of value changes for the control that emits every time the
* value of the control changes in the UI or programmatically.
* If the control is not present, null is returned.
*/
get: function () {
return this.control ? this.control.valueChanges : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlDirective.prototype, "path", {
/**
* @description
* 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.
*/
get: function () { return null; },
enumerable: true,
configurable: true
});
/**
* @description
* Resets the control with the provided value if the control is present.
*/
AbstractControlDirective.prototype.reset = function (value) {
if (value === void 0) { value = undefined; }
if (this.control)
this.control.reset(value);
};
/**
* @description
* Reports whether the control with the given path has the error specified.
*
* @param errorCode The code of the error to check
* @param path A list of control names that designates how to move from the current control
* to the control that should be queried for errors.
*
* @usageNotes
* For example, for the following `FormGroup`:
*
* ```
* form = new FormGroup({
* address: new FormGroup({ street: new FormControl() })
* });
* ```
*
* The path to the 'street' control from the root form would be 'address' -> 'street'.
*
* It can be provided to this method in one of two formats:
*
* 1. An array of string control names, e.g. `['address', 'street']`
* 1. A period-delimited list of control names in one string, e.g. `'address.street'`
*
* If no path is given, this method checks for the error on the current control.
*
* @returns whether the given error is present in the control at the given path.
*
* If the control is not present, false is returned.
*/
AbstractControlDirective.prototype.hasError = function (errorCode, path) {
return this.control ? this.control.hasError(errorCode, path) : false;
};
/**
* @description
* Reports error data for the control with the given path.
*
* @param errorCode The code of the error to check
* @param path A list of control names that designates how to move from the current control
* to the control that should be queried for errors.
*
* @usageNotes
* For example, for the following `FormGroup`:
*
* ```
* form = new FormGroup({
* address: new FormGroup({ street: new FormControl() })
* });
* ```
*
* The path to the 'street' control from the root form would be 'address' -> 'street'.
*
* It can be provided to this method in one of two formats:
*
* 1. An array of string control names, e.g. `['address', 'street']`
* 1. A period-delimited list of control names in one string, e.g. `'address.street'`
*
* @returns error data for that particular error. If the control or error is not present,
* null is returned.
*/
AbstractControlDirective.prototype.getError = function (errorCode, path) {
return this.control ? this.control.getError(errorCode, path) : null;
};
return AbstractControlDirective;
}());
/**
* @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
*/
/**
* @description
* A base class for directives that contain multiple registered instances of `NgControl`.
* Only used by the forms module.
*
* @publicApi
*/
var ControlContainer = /** @class */ (function (_super) {
__extends(ControlContainer, _super);
function ControlContainer() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(ControlContainer.prototype, "formDirective", {
/**
* @description
* The top-level form directive for the control.
*/
get: function () { return null; },
enumerable: true,
configurable: true
});
Object.defineProperty(ControlContainer.prototype, "path", {
/**
* @description
* The path to this group.
*/
get: function () { return null; },
enumerable: true,
configurable: true
});
return ControlContainer;
}(AbstractControlDirective));
/**
* @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
*/
function unimplemented() {
throw new Error('unimplemented');
}
/**
* @description
* A base class that all control `FormControl`-based directives extend. It binds a `FormControl`
* object to a DOM element.
*
* @publicApi
*/
var NgControl = /** @class */ (function (_super) {
__extends(NgControl, _super);
function NgControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
/**
* @description
* The parent form for the control.
*
* @internal
*/
_this._parent = null;
/**
* @description
* The name for the control
*/
_this.name = null;
/**
* @description
* The value accessor for the control
*/
_this.valueAccessor = null;
/**
* @description
* The uncomposed array of synchronous validators for the control
*
* @internal
*/
_this._rawValidators = [];
/**
* @description
* The uncomposed array of async validators for the control
*
* @internal
*/
_this._rawAsyncValidators = [];
return _this;
}
Object.defineProperty(NgControl.prototype, "validator", {
/**
* @description
* The registered synchronous validator function for the control
*
* @throws An exception that this method is not implemented
*/
get: function () { return unimplemented(); },
enumerable: true,
configurable: true
});
Object.defineProperty(NgControl.prototype, "asyncValidator", {
/**
* @description
* The registered async validator function for the control
*
* @throws An exception that this method is not implemented
*/
get: function () { return unimplemented(); },
enumerable: true,
configurable: true
});
return NgControl;
}(AbstractControlDirective));
/**
* @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
*/
var AbstractControlStatus = /** @class */ (function () {
function AbstractControlStatus(cd) {
this._cd = cd;
}
Object.defineProperty(AbstractControlStatus.prototype, "ngClassUntouched", {
get: function () { return this._cd.control ? this._cd.control.untouched : false; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlStatus.prototype, "ngClassTouched", {
get: function () { return this._cd.control ? this._cd.control.touched : false; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlStatus.prototype, "ngClassPristine", {
get: function () { return this._cd.control ? this._cd.control.pristine : false; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlStatus.prototype, "ngClassDirty", {
get: function () { return this._cd.control ? this._cd.control.dirty : false; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlStatus.prototype, "ngClassValid", {
get: function () { return this._cd.control ? this._cd.control.valid : false; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlStatus.prototype, "ngClassInvalid", {
get: function () { return this._cd.control ? this._cd.control.invalid : false; },
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractControlStatus.prototype, "ngClassPending", {
get: function () { return this._cd.control ? this._cd.control.pending : false; },
enumerable: true,
configurable: true
});
return AbstractControlStatus;
}());
var ngControlStatusHost = {
'[class.ng-untouched]': 'ngClassUntouched',
'[class.ng-touched]': 'ngClassTouched',
'[class.ng-pristine]': 'ngClassPristine',
'[class.ng-dirty]': 'ngClassDirty',
'[class.ng-valid]': 'ngClassValid',
'[class.ng-invalid]': 'ngClassInvalid',
'[class.ng-pending]': 'ngClassPending',
};
/**
* @description
* Directive automatically applied to Angular form controls that sets CSS classes
* based on control status.
*
* @usageNotes
*
* ### CSS classes applied
*
* The following classes are applied as the properties become true:
*
* * ng-valid
* * ng-invalid
* * ng-pending
* * ng-pristine
* * ng-dirty
* * ng-untouched
* * ng-touched
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var NgControlStatus = /** @class */ (function (_super) {
__extends(NgControlStatus, _super);
function NgControlStatus(cd) {
return _super.call(this, cd) || this;
}
NgControlStatus = __decorate([
Directive({ selector: '[formControlName],[ngModel],[formControl]', host: ngControlStatusHost }),
__param(0, Self()),
__metadata("design:paramtypes", [NgControl])
], NgControlStatus);
return NgControlStatus;
}(AbstractControlStatus));
/**
* @description
* Directive automatically applied to Angular form groups that sets CSS classes
* based on control status (valid/invalid/dirty/etc).
*
* @see `NgControlStatus`
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var NgControlStatusGroup = /** @class */ (function (_super) {
__extends(NgControlStatusGroup, _super);
function NgControlStatusGroup(cd) {
return _super.call(this, cd) || this;
}
NgControlStatusGroup = __decorate([
Directive({
selector: '[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]',
host: ngControlStatusHost
}),
__param(0, Self()),
__metadata("design:paramtypes", [ControlContainer])
], NgControlStatusGroup);
return NgControlStatusGroup;
}(AbstractControlStatus));
/**
* @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
*/
function isEmptyInputValue(value) {
// we don't check for string here so it also works with arrays
return value == null || value.length === 0;
}
/**
* @description
* An `InjectionToken` for registering additional synchronous validators used with `AbstractControl`s.
*
* @see `NG_ASYNC_VALIDATORS`
*
* @usageNotes
*
* ### Providing a custom validator
*
* The following example registers a custom validator directive. Adding the validator to the
* existing collection of validators requires the `multi: true` option.
*
* ```typescript
* @Directive({
* selector: '[customValidator]',
* providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]
* })
* class CustomValidatorDirective implements Validator {
* validate(control: AbstractControl): ValidationErrors | null {
* return { 'custom': true };
* }
* }
* ```
*
* @publicApi
*/
var NG_VALIDATORS = new InjectionToken('NgValidators');
/**
* @description
* An `InjectionToken` for registering additional asynchronous validators used with `AbstractControl`s.
*
* @see `NG_VALIDATORS`
*
* @publicApi
*/
var NG_ASYNC_VALIDATORS = new InjectionToken('NgAsyncValidators');
var 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])?)*$/;
/**
* @description
* Provides a set of built-in validators that can be used by form controls.
*
* A validator is a function that processes a `FormControl` or collection of
* controls and returns an error map or null. A null map means that validation has passed.
*
* @see [Form Validation](/guide/form-validation)
*
* @publicApi
*/
var Validators = /** @class */ (function () {
function Validators() {
}
/**
* @description
* Validator that requires the control's value to be greater than or equal to the provided number.
* The validator exists only as a function and not as a directive.
*
* @usageNotes
*
* ### Validate against a minimum of 3
*
* ```typescript
* const control = new FormControl(2, Validators.min(3));
*
* console.log(control.errors); // {min: {min: 3, actual: 2}}
* ```
*
* @returns A validator function that returns an error map with the
* `min` property if the validation check fails, otherwise `null`.
*
*/
Validators.min = function (min) {
return function (control) {
if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) {
return null; // don't validate empty values to allow optional controls
}
var 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;
};
};
/**
* @description
* Validator that requires the control's value to be less than or equal to the provided number.
* The validator exists only as a function and not as a directive.
*
* @usageNotes
*
* ### Validate against a maximum of 15
*
* ```typescript
* const control = new FormControl(16, Validators.max(15));
*
* console.log(control.errors); // {max: {max: 15, actual: 16}}
* ```
*
* @returns A validator function that returns an error map with the
* `max` property if the validation check fails, otherwise `null`.
*
*/
Validators.max = function (max) {
return function (control) {
if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) {
return null; // don't validate empty values to allow optional controls
}
var 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;
};
};
/**
* @description
* Validator that requires the control have a non-empty value.
*
* @usageNotes
*
* ### Validate that the field is non-empty
*
* ```typescript
* const control = new FormControl('', Validators.required);
*
* console.log(control.errors); // {required: true}
* ```
*
* @returns An error map with the `required` property
* if the validation check fails, otherwise `null`.
*
*/
Validators.required = function (control) {
return isEmptyInputValue(control.value) ? { 'required': true } : null;
};
/**
* @description
* Validator that requires the control's value be true. This validator is commonly
* used for required checkboxes.
*
* @usageNotes
*
* ### Validate that the field value is true
*
* ```typescript
* const control = new FormControl('', Validators.requiredTrue);
*
* console.log(control.errors); // {required: true}
* ```
*
* @returns An error map that contains the `required` property
* set to `true` if the validation check fails, otherwise `null`.
*/
Validators.requiredTrue = function (control) {
return control.value === true ? null : { 'required': true };
};
/**
* @description
* Validator that requires the control's value pass an email validation test.
*
* @usageNotes
*
* ### Validate that the field matches a valid email pattern
*
* ```typescript
* const control = new FormControl('bad@', Validators.email);
*
* console.log(control.errors); // {email: true}
* ```
*
* @returns An error map with the `email` property
* if the validation check fails, otherwise `null`.
*
*/
Validators.email = function (control) {
if (isEmptyInputValue(control.value)) {
return null; // don't validate empty values to allow optional controls
}
return EMAIL_REGEXP.test(control.value) ? null : { 'email': true };
};
/**
* @description
* Validator that requires the length of the control's value to be greater than or equal
* to the provided minimum length. This validator is also provided by default if you use the
* the HTML5 `minlength` attribute.
*
* @usageNotes
*
* ### Validate that the field has a minimum of 3 characters
*
* ```typescript
* const control = new FormControl('ng', Validators.minLength(3));
*
* console.log(control.errors); // {minlength: {requiredLength: 3, actualLength: 2}}
* ```
*
* ```html
*
* ```
*
* @returns A validator function that returns an error map with the
* `minlength` if the validation check fails, otherwise `null`.
*/
Validators.minLength = function (minLength) {
return function (control) {
if (isEmptyInputValue(control.value)) {
return null; // don't validate empty values to allow optional controls
}
var length = control.value ? control.value.length : 0;
return length < minLength ?
{ 'minlength': { 'requiredLength': minLength, 'actualLength': length } } :
null;
};
};
/**
* @description
* Validator that requires the length of the control's value to be less than or equal
* to the provided maximum length. This validator is also provided by default if you use the
* the HTML5 `maxlength` attribute.
*
* @usageNotes
*
* ### Validate that the field has maximum of 5 characters
*
* ```typescript
* const control = new FormControl('Angular', Validators.maxLength(5));
*
* console.log(control.errors); // {maxlength: {requiredLength: 5, actualLength: 7}}
* ```
*
* ```html
*
* ```
*
* @returns A validator function that returns an error map with the
* `maxlength` property if the validation check fails, otherwise `null`.
*/
Validators.maxLength = function (maxLength) {
return function (control) {
var length = control.value ? control.value.length : 0;
return length > maxLength ?
{ 'maxlength': { 'requiredLength': maxLength, 'actualLength': length } } :
null;
};
};
/**
* @description
* Validator that requires the control's value to match a regex pattern. This validator is also
* provided by default if you use the HTML5 `pattern` attribute.
*
* Note that if a Regexp is provided, the Regexp is used as is to test the values. On the other
* hand, if a string is passed, the `^` character is prepended and the `$` character is
* appended to the provided string (if not already present), and the resulting regular
* expression is used to test the values.
*
* @usageNotes
*
* ### Validate that the field only contains letters or spaces
*
* ```typescript
* const control = new FormControl('1', Validators.pattern('[a-zA-Z ]*'));
*
* console.log(control.errors); // {pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}}
* ```
*
* ```html
*
* ```
*
* @returns A validator function that returns an error map with the
* `pattern` property if the validation check fails, otherwise `null`.
*/
Validators.pattern = function (pattern) {
if (!pattern)
return Validators.nullValidator;
var regex;
var 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 function (control) {
if (isEmptyInputValue(control.value)) {
return null; // don't validate empty values to allow optional controls
}
var value = control.value;
return regex.test(value) ? null :
{ 'pattern': { 'requiredPattern': regexStr, 'actualValue': value } };
};
};
/**
* @description
* Validator that performs no operation.
*/
Validators.nullValidator = function (control) { return null; };
Validators.compose = function (validators) {
if (!validators)
return null;
var presentValidators = validators.filter(isPresent);
if (presentValidators.length == 0)
return null;
return function (control) {
return _mergeErrors(_executeValidators(control, presentValidators));
};
};
/**
* @description
* Compose multiple async validators into a single function that returns the union
* of the individual error objects for the provided control.
*
* @returns A validator function that returns an error map with the
* merged error objects of the async validators if the validation check fails, otherwise `null`.
*/
Validators.composeAsync = function (validators) {
if (!validators)
return null;
var presentValidators = validators.filter(isPresent);
if (presentValidators.length == 0)
return null;
return function (control) {
var observables = _executeAsyncValidators(control, presentValidators).map(toObservable);
return forkJoin(observables).pipe(map(_mergeErrors));
};
};
return Validators;
}());
function isPresent(o) {
return o != null;
}
function toObservable(r) {
var obs = ɵisPromise(r) ? from(r) : r;
if (!(ɵisObservable(obs))) {
throw new Error("Expected validator to return Promise or Observable.");
}
return obs;
}
function _executeValidators(control, validators) {
return validators.map(function (v) { return v(control); });
}
function _executeAsyncValidators(control, validators) {
return validators.map(function (v) { return v(control); });
}
function _mergeErrors(arrayOfErrors) {
var res = arrayOfErrors.reduce(function (res, errors) {
return errors != null ? __assign({}, res, errors) : res;
}, {});
return Object.keys(res).length === 0 ? null : res;
}
/**
* @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
*/
function normalizeValidator(validator) {
if (validator.validate) {
return function (c) { return validator.validate(c); };
}
else {
return validator;
}
}
function normalizeAsyncValidator(validator) {
if (validator.validate) {
return function (c) { return validator.validate(c); };
}
else {
return validator;
}
}
/**
* @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
*/
var NUMBER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return NumberValueAccessor; }),
multi: true
};
/**
* @description
* The `ControlValueAccessor` for writing a number value and listening to number input changes.
* The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
* directives.
*
* @usageNotes
*
* ### Using a number input with a reactive form.
*
* The following example shows how to use a number input with a reactive form.
*
* ```ts
* const totalCountControl = new FormControl();
* ```
*
* ```
*
* ```
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var NumberValueAccessor = /** @class */ (function () {
function NumberValueAccessor(_renderer, _elementRef) {
this._renderer = _renderer;
this._elementRef = _elementRef;
/**
* @description
* The registered callback function called when a change or input event occurs on the input
* element.
*/
this.onChange = function (_) { };
/**
* @description
* The registered callback function called when a blur event occurs on the input element.
*/
this.onTouched = function () { };
}
/**
* Sets the "value" property on the input element.
*
* @param value The checked value
*/
NumberValueAccessor.prototype.writeValue = function (value) {
// The value needs to be normalized for IE9, otherwise it is set to 'null' when null
var normalizedValue = value == null ? '' : value;
this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
};
/**
* @description
* Registers a function called when the control value changes.
*
* @param fn The callback function
*/
NumberValueAccessor.prototype.registerOnChange = function (fn) {
this.onChange = function (value) { fn(value == '' ? null : parseFloat(value)); };
};
/**
* @description
* Registers a function called when the control is touched.
*
* @param fn The callback function
*/
NumberValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };
/**
* Sets the "disabled" property on the input element.
*
* @param isDisabled The disabled value
*/
NumberValueAccessor.prototype.setDisabledState = function (isDisabled) {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
};
NumberValueAccessor = __decorate([
Directive({
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]
}),
__metadata("design:paramtypes", [Renderer2, ElementRef])
], NumberValueAccessor);
return NumberValueAccessor;
}());
/**
* @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
*/
var RADIO_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return RadioControlValueAccessor; }),
multi: true
};
/**
* @description
* Class used by Angular to track radio buttons. For internal use only.
*/
var RadioControlRegistry = /** @class */ (function () {
function RadioControlRegistry() {
this._accessors = [];
}
/**
* @description
* Adds a control to the internal registry. For internal use only.
*/
RadioControlRegistry.prototype.add = function (control, accessor) {
this._accessors.push([control, accessor]);
};
/**
* @description
* Removes a control from the internal registry. For internal use only.
*/
RadioControlRegistry.prototype.remove = function (accessor) {
for (var i = this._accessors.length - 1; i >= 0; --i) {
if (this._accessors[i][1] === accessor) {
this._accessors.splice(i, 1);
return;
}
}
};
/**
* @description
* Selects a radio button. For internal use only.
*/
RadioControlRegistry.prototype.select = function (accessor) {
var _this = this;
this._accessors.forEach(function (c) {
if (_this._isSameGroup(c, accessor) && c[1] !== accessor) {
c[1].fireUncheck(accessor.value);
}
});
};
RadioControlRegistry.prototype._isSameGroup = function (controlPair, accessor) {
if (!controlPair[0].control)
return false;
return controlPair[0]._parent === accessor._control._parent &&
controlPair[1].name === accessor.name;
};
RadioControlRegistry = __decorate([
Injectable()
], RadioControlRegistry);
return RadioControlRegistry;
}());
/**
* @description
* The `ControlValueAccessor` for writing radio control values and listening to radio control
* changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
* `NgModel` directives.
*
* @usageNotes
*
* ### Using radio buttons with reactive form directives
*
* The follow example shows how to use radio buttons in a reactive form. When using radio buttons in
* a reactive form, radio buttons in the same group should have the same `formControlName`.
* Providing a `name` attribute is optional.
*
* {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var RadioControlValueAccessor = /** @class */ (function () {
function RadioControlValueAccessor(_renderer, _elementRef, _registry, _injector) {
this._renderer = _renderer;
this._elementRef = _elementRef;
this._registry = _registry;
this._injector = _injector;
/**
* @description
* The registered callback function called when a change event occurs on the input element.
*/
this.onChange = function () { };
/**
* @description
* The registered callback function called when a blur event occurs on the input element.
*/
this.onTouched = function () { };
}
/**
* @description
* A lifecycle method called when the directive is initialized. For internal use only.
*
* @param changes A object of key/value pairs for the set of changed inputs.
*/
RadioControlValueAccessor.prototype.ngOnInit = function () {
this._control = this._injector.get(NgControl);
this._checkName();
this._registry.add(this._control, this);
};
/**
* @description
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
*
* @param changes A object of key/value pairs for the set of changed inputs.
*/
RadioControlValueAccessor.prototype.ngOnDestroy = function () { this._registry.remove(this); };
/**
* @description
* Sets the "checked" property value on the radio input element.
*
* @param value The checked value
*/
RadioControlValueAccessor.prototype.writeValue = function (value) {
this._state = value === this.value;
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', this._state);
};
/**
* @description
* Registers a function called when the control value changes.
*
* @param fn The callback function
*/
RadioControlValueAccessor.prototype.registerOnChange = function (fn) {
var _this = this;
this._fn = fn;
this.onChange = function () {
fn(_this.value);
_this._registry.select(_this);
};
};
/**
* Sets the "value" on the radio input element and unchecks it.
*
* @param value
*/
RadioControlValueAccessor.prototype.fireUncheck = function (value) { this.writeValue(value); };
/**
* @description
* Registers a function called when the control is touched.
*
* @param fn The callback function
*/
RadioControlValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };
/**
* Sets the "disabled" property on the input element.
*
* @param isDisabled The disabled value
*/
RadioControlValueAccessor.prototype.setDisabledState = function (isDisabled) {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
};
RadioControlValueAccessor.prototype._checkName = function () {
if (this.name && this.formControlName && this.name !== this.formControlName) {
this._throwNameError();
}
if (!this.name && this.formControlName)
this.name = this.formControlName;
};
RadioControlValueAccessor.prototype._throwNameError = function () {
throw new Error("\n If you define both a name and a formControlName attribute on your radio button, their values\n must match. Ex: \n ");
};
__decorate([
Input(),
__metadata("design:type", String)
], RadioControlValueAccessor.prototype, "name", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], RadioControlValueAccessor.prototype, "formControlName", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], RadioControlValueAccessor.prototype, "value", void 0);
RadioControlValueAccessor = __decorate([
Directive({
selector: 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]',
host: { '(change)': 'onChange()', '(blur)': 'onTouched()' },
providers: [RADIO_VALUE_ACCESSOR]
}),
__metadata("design:paramtypes", [Renderer2, ElementRef,
RadioControlRegistry, Injector])
], RadioControlValueAccessor);
return RadioControlValueAccessor;
}());
/**
* @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
*/
var RANGE_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return RangeValueAccessor; }),
multi: true
};
/**
* @description
* The `ControlValueAccessor` for writing a range value and listening to range input changes.
* The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
* directives.
*
* @usageNotes
*
* ### Using a range input with a reactive form
*
* The following example shows how to use a range input with a reactive form.
*
* ```ts
* const ageControl = new FormControl();
* ```
*
* ```
*
* ```
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
var RangeValueAccessor = /** @class */ (function () {
function RangeValueAccessor(_renderer, _elementRef) {
this._renderer = _renderer;
this._elementRef = _elementRef;
/**
* @description
* The registered callback function called when a change or input event occurs on the input
* element.
*/
this.onChange = function (_) { };
/**
* @description
* The registered callback function called when a blur event occurs on the input element.
*/
this.onTouched = function () { };
}
/**
* Sets the "value" property on the input element.
*
* @param value The checked value
*/
RangeValueAccessor.prototype.writeValue = function (value) {
this._renderer.setProperty(this._elementRef.nativeElement, 'value', parseFloat(value));
};
/**
* @description
* Registers a function called when the control value changes.
*
* @param fn The callback function
*/
RangeValueAccessor.prototype.registerOnChange = function (fn) {
this.onChange = function (value) { fn(value == '' ? null : parseFloat(value)); };
};
/**
* @description
* Registers a function called when the control is touched.
*
* @param fn The callback function
*/
RangeValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };
/**
* Sets the "disabled" property on the range input element.
*
* @param isDisabled The disabled value
*/
RangeValueAccessor.prototype.setDisabledState = function (isDisabled) {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
};
RangeValueAccessor = __decorate([
Directive({
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]
}),
__metadata("design:paramtypes", [Renderer2, ElementRef])
], RangeValueAccessor);
return RangeValueAccessor;
}());
/**
* @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
*/
var FormErrorExamples = {
formControlName: "\n
\n \n
\n\n In your class:\n\n this.myGroup = new FormGroup({\n firstName: new FormControl()\n });",
formGroupName: "\n
\n
\n \n
\n
\n\n In your class:\n\n this.myGroup = new FormGroup({\n person: new FormGroup({ firstName: new FormControl() })\n });",
formArrayName: "\n
\n
\n
\n \n
\n
\n
\n\n In your class:\n\n this.cityArray = new FormArray([new FormControl('SF')]);\n this.myGroup = new FormGroup({\n cities: this.cityArray\n });",
ngModelGroup: "\n ",
ngModelWithFormGroup: "\n
\n \n \n
\n "
};
/**
* @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
*/
var ReactiveErrors = /** @class */ (function () {
function ReactiveErrors() {
}
ReactiveErrors.controlParentException = function () {
throw new Error("formControlName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n " + FormErrorExamples.formControlName);
};
ReactiveErrors.ngModelGroupException = function () {
throw new Error("formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents\n that also have a \"form\" prefix: formGroupName, formArrayName, or formGroup.\n\n Option 1: Update the parent to be formGroupName (reactive form strategy)\n\n " + FormErrorExamples.formGroupName + "\n\n Option 2: Use ngModel instead of formControlName (template-driven strategy)\n\n " + FormErrorExamples.ngModelGroup);
};
ReactiveErrors.missingFormException = function () {
throw new Error("formGroup expects a FormGroup instance. Please pass one in.\n\n Example:\n\n " + FormErrorExamples.formControlName);
};
ReactiveErrors.groupParentException = function () {
throw new Error("formGroupName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n " + FormErrorExamples.formGroupName);
};
ReactiveErrors.arrayParentException = function () {
throw new Error("formArrayName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n " + FormErrorExamples.formArrayName);
};
ReactiveErrors.disabledAttrWarning = function () {
console.warn("\n It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true\n when you set up this control in your component class, the disabled attribute will actually be set in the DOM for\n you. We recommend using this approach to avoid 'changed after checked' errors.\n \n Example: \n form = new FormGroup({\n first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),\n last: new FormControl('Drew', Validators.required)\n });\n ");
};
ReactiveErrors.ngModelWarning = function (directiveName) {
console.warn("\n It looks like you're using ngModel on the same form field as " + directiveName + ". \n Support for using the ngModel input property and ngModelChange event with \n reactive form directives has been deprecated in Angular v6 and will be removed \n in Angular v7.\n \n For more information on this, see our API docs here:\n https://angular.io/api/forms/" + (directiveName === 'formControl' ? 'FormControlDirective'
: 'FormControlName') + "#use-with-ngmodel\n ");
};
return ReactiveErrors;
}());
/**
* @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
*/
var SELECT_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(function () { return SelectControlValueAccessor; }),
multi: true
};
function _buildValueString(id, value) {
if (id == null)
return "" + value;
if (value && typeof value === 'object')
value = 'Object';
return (id + ": " + value).slice(0, 50);
}
function _extractId(valueString) {
return valueString.split(':')[0];
}
/**
* @description
* The `ControlValueAccessor` for writing select control values and listening to select control
* changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
* `NgModel` directives.
*
* @usageNotes
*
* ### Using select controls in a reactive form
*
* The following examples show how to use a select control in a reactive form.
*
* {@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'}
*
* ### Using select controls in a template-driven form
*
* To use a select in a template-driven form, simply add an `ngModel` and a `name`
* attribute to the main `