@crnk/angular-ngrx
Version:
Angular helper library for ngrx-json-api and crnk:
170 lines • 7.11 kB
JavaScript
// copy/pasted from @angular/forms to due the lack of customizability of their implementation
import { AbstractControl, AbstractControlDirective, AsyncValidator, AsyncValidatorFn, CheckboxControlValueAccessor, ControlContainer, ControlValueAccessor, DefaultValueAccessor, FormControl, NgControl, RadioControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor, Validator, ValidatorFn, Validators } from '@angular/forms';
import { CrnkControl } from './crnk.expression.form.model.base';
import { ExpressionDefaultValueAccessorDirective } from './crnk.expression.form.model.accessor';
export function normalizeValidator(validator) {
if (validator.validate) {
return function (c) { return validator.validate(c); };
}
else {
return validator;
}
}
export function normalizeAsyncValidator(validator) {
if (validator.validate) {
return function (c) { return validator.validate(c); };
}
else {
return validator;
}
}
export function looseIdentical(a, b) {
return a === b || typeof a === 'number' && typeof b === 'number' && isNaN(a) && isNaN(b);
}
export function isPresent(obj) {
return obj !== null;
}
export function controlPath(name, parent) {
return parent.path.concat([name]);
}
export function setUpControl(control, dir) {
if (!control) {
_throwError(dir, 'Cannot find control with');
}
if (!dir.valueAccessor) {
_throwError(dir, 'No value accessor for form control with');
}
control.validator = Validators.compose([control.validator, dir.validator]);
control.asyncValidator = Validators.composeAsync([control.asyncValidator, dir.asyncValidator]);
dir.valueAccessor.writeValue(control.value);
// view -> model
dir.valueAccessor.registerOnChange(function (newValue) {
dir.viewToModelUpdate(newValue);
control.markAsDirty();
control.setValue(newValue, { emitModelToViewChange: false });
});
// touched
dir.valueAccessor.registerOnTouched(function () { return control.markAsTouched(); });
control.registerOnChange(function (newValue, emitModelEvent) {
// control -> view
dir.valueAccessor.writeValue(newValue);
// control -> ngModel
if (emitModelEvent) {
dir.viewToModelUpdate(newValue);
}
});
if (dir.valueAccessor.setDisabledState) {
control.registerOnDisabledChange(function (isDisabled) {
dir.valueAccessor.setDisabledState(isDisabled);
});
}
// re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4
dir._rawValidators.forEach(function (validator) {
if (validator.registerOnValidatorChange) {
validator.registerOnValidatorChange(function () { return control.updateValueAndValidity(); });
}
});
dir._rawAsyncValidators.forEach(function (validator) {
if (validator.registerOnValidatorChange) {
validator.registerOnValidatorChange(function () { return control.updateValueAndValidity(); });
}
});
}
function _noControlError(dir) {
return _throwError(dir, 'There is no FormControl instance attached to form control element with');
}
function _throwError(dir, message) {
var messageEnd;
if (dir.path.length > 1) {
messageEnd = "path: '" + dir.path.join(' -> ') + "'";
}
else if (dir.path[0]) {
messageEnd = "name: '" + dir.path + "'";
}
else {
messageEnd = 'unspecified name attribute';
}
throw new Error(message + " " + messageEnd);
}
export function composeValidators(validators) {
return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null;
}
export function composeAsyncValidators(validators) {
return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :
null;
}
export function isPropertyUpdated(changes, viewModel) {
if (!changes.hasOwnProperty('pathModel')) {
return false;
}
var change = changes['pathModel'];
if (change.isFirstChange()) {
return true;
}
return !looseIdentical(viewModel, change.currentValue);
}
var BUILTIN_ACCESSORS = [
CheckboxControlValueAccessor,
SelectControlValueAccessor,
SelectMultipleControlValueAccessor,
RadioControlValueAccessor,
];
export function isBuiltInAccessor(valueAccessor) {
return BUILTIN_ACCESSORS.some(function (a) { return valueAccessor.constructor === a; });
}
// TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented
export function selectValueAccessor(dir, valueAccessors) {
if (!valueAccessors) {
return null;
}
var defaultAccessor;
var builtinAccessor;
var customAccessor;
valueAccessors.forEach(function (v) {
if (v.constructor === DefaultValueAccessor || v.constructor === ExpressionDefaultValueAccessorDirective) {
defaultAccessor = v;
}
else if (isBuiltInAccessor(v)) {
if (builtinAccessor) {
_throwError(dir, 'More than one built-in value accessor matches form control with');
}
builtinAccessor = v;
}
else {
if (customAccessor) {
_throwError(dir, 'More than one custom value accessor matches form control with');
}
customAccessor = v;
}
});
if (customAccessor) {
return customAccessor;
}
if (builtinAccessor) {
return builtinAccessor;
}
if (defaultAccessor) {
return defaultAccessor;
}
_throwError(dir, 'No valid value accessor for form control with');
return null;
}
var TemplateDrivenErrors = /** @class */ (function () {
function TemplateDrivenErrors() {
}
TemplateDrivenErrors.modelParentException = function () {
throw new Error("\n ngModel cannot be used to register form controls with a parent formGroup directive.");
};
TemplateDrivenErrors.formGroupNameException = function () {
throw new Error("\n ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive.");
};
TemplateDrivenErrors.missingNameException = function () {
throw new Error("If ngModel is used within a form tag, either the name attribute must be set or the form\n control must be defined as 'standalone' in ngModelOptions.\n Example 1: <input [(ngModel)]=\"person.firstName\" name=\"first\">\n Example 2: <input [(ngModel)]=\"person.firstName\" [ngModelOptions]=\"{standalone: true}\">");
};
TemplateDrivenErrors.modelGroupParentException = function () {
throw new Error("\n ngModelGroup cannot be used with a parent formGroup directive.");
};
return TemplateDrivenErrors;
}());
export { TemplateDrivenErrors };
//# sourceMappingURL=crnk.expression.form.utils.js.map