@developerwellness/angular-typed-forms
Version:
288 lines (284 loc) • 10.2 kB
JavaScript
import { InjectionToken } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
function createTypedFormArray(controls, validatorOrOpts, asyncValidator) {
return new TypedFormArray(controls, validatorOrOpts, asyncValidator);
}
class TypedFormArrayIterator {
constructor(_formArray) {
this._formArray = _formArray;
this._index = 0;
}
next() {
if (this._index < this._formArray.length) {
const control = this._formArray.controls[this._index];
this._index++;
return {
value: control,
done: false,
};
}
return {
value: null,
done: true,
};
}
}
class TypedFormArray extends FormArray {
constructor(controls, validatorOrOpts, asyncValidator) {
super(controls, validatorOrOpts, asyncValidator);
}
add(value) {
super.push(createTypedControls(value));
}
[Symbol.iterator]() {
return new TypedFormArrayIterator(this);
}
}
function createTypedFormControl(formState, validatorOrOpts, asyncValidator) {
return new TypedFormControl(formState, validatorOrOpts, asyncValidator);
}
class TypedFormControl extends FormControl {
constructor(formState, validatorOrOpts, asyncValidator) {
super(formState, validatorOrOpts, asyncValidator);
}
setValue(value, options) {
super.setValue(value, options);
}
patchValue(value, options) {
super.patchValue(value, options);
}
reset(formState, options) {
super.reset(formState, options);
}
}
function createTypedFormGroup(controls, validatorOrOpts, asyncValidator) {
return new TypedFormGroup(controls, validatorOrOpts, asyncValidator);
}
class TypedFormGroup extends FormGroup {
constructor(controls, validatorOrOpts, asyncValidator) {
super(controls, validatorOrOpts, asyncValidator);
}
setReadonly(_value) { }
getValue() {
return this.value;
}
}
function _hasValueChanged(valueA, valueB) {
const result = !deepEquals(valueA.value, valueB);
return result;
}
function _isArray(value) {
return Array.isArray(value);
}
function _isObject(value) {
return !!(typeof value === 'object' && value);
}
function _shouldBeProcessedFactory(options) {
return (value) => !options.ignoreFields.includes(value);
}
function _containsErrors(value) {
if (!(value === null || value === void 0 ? void 0 : value.errors))
return false;
return true;
}
function createTypedFormGroupControls(value, options) {
if (!value)
return null;
return Object.keys(value)
.map((key) => [key, createTypedControls(value[key], options, key)])
.reduce((formGroupControls, [key, formControl]) => (Object.assign(Object.assign({}, formGroupControls), { [key]: formControl })), {});
}
function _isTypedFormModel(formValue) {
return (_isObject(formValue) &&
'value' in formValue &&
('validatorOrOpts' in formValue || 'asyncValidator' in formValue));
}
function createTypedControls(formValue, options = { ignoreFields: [] }, key) {
const shouldBeProcessed = _shouldBeProcessedFactory(options);
if (_isArray(formValue) && shouldBeProcessed(key)) {
return createTypedFormArray(formValue.map((item) => createTypedControls(item, options, key)));
}
else if (_isObject(formValue) &&
!_isTypedFormModel(formValue) &&
shouldBeProcessed(key)) {
return createTypedFormGroup(createTypedFormGroupControls(formValue, options));
}
else {
return _isTypedFormModel(formValue)
? createTypedFormControl(formValue.value, formValue.validatorOrOpts, formValue.asyncValidator)
: createTypedFormControl(formValue);
}
}
function removeFormArrayControls(formArray, formValue) {
forEach(new Array(formArray.length - formValue.length), () => {
formArray.removeAt(0, { emitEvent: false });
});
}
function updateTypedFormArray(formArray, formValue, options = { ignoreFields: [] }) {
if (formArray.length > formValue.length) {
removeFormArrayControls(formArray, formValue);
forEach(formArray.controls, (item, index) => {
updateTypedFormControls(item, formValue[index], options);
});
}
else {
forEach(formValue, (item, index) => {
if (formArray.controls[index]) {
updateTypedFormControls(formArray.controls[index], item, options);
}
else {
//Should be fixed with https://github.com/angular/angular/issues/20439#issuecomment-763976919
formArray.push(createTypedControls(item, options), { emitEvent: false });
}
});
}
}
function updateTypedFormGroup(formGroup, formValue, options = { ignoreFields: [] }) {
if (!formValue) {
Object.keys(formGroup.value)
.filter((key) => formGroup &&
formGroup.contains &&
formGroup.contains(key))
.map((key) => formGroup.get(key))
.forEach((itemControl) => {
itemControl.patchValue(null, { emitEvent: false });
});
}
else {
Object.keys(formValue)
.filter((key) => formGroup &&
formGroup.contains &&
formGroup.contains(key))
.map((key) => [formValue[key], formGroup.get(key), key])
.forEach(([item, itemControl, key]) => updateTypedFormControls(itemControl, item, options, key));
Object.keys(formValue)
.filter((key) => formGroup &&
formGroup.contains &&
!formGroup.contains(key))
.map((key) => [key, formValue[key]])
.forEach(([key, item]) => formGroup.addControl(key, createTypedControls(item, options, key), {
emitEvent: false,
}));
}
}
function updateTypedFormControl(formControl, formValue) {
if (_containsErrors(formValue)) {
const { errors } = formValue;
formControl.setErrors(errors);
}
else {
formControl.patchValue(formValue, { emitEvent: false });
formControl.setErrors(null);
}
}
function updateTypedFormControls(formControl, formValue, options = { ignoreFields: [] }, key) {
const _shouldBeIgnored = _shouldBeProcessedFactory(options);
if (_isArray(formValue || formControl.value) &&
_shouldBeIgnored(key) &&
_hasValueChanged(formControl, formValue)) {
updateTypedFormArray(formControl, formValue, options);
}
else if (_isObject(formControl.value || formControl.value) &&
_shouldBeIgnored(key) &&
_hasValueChanged(formControl, formValue) &&
(formControl === null || formControl === void 0 ? void 0 : formControl.controls)) {
updateTypedFormGroup(formControl, formValue, options);
}
else if (_hasValueChanged(formControl, formValue)) {
updateTypedFormControl(formControl, formValue);
}
}
const FORM_GROUP_PROP = 'formGroup';
const VALUE_PROP = 'value';
function typedFormBuilderFactory(defaultValue, options = { ignoreFields: [] }) {
if (!defaultValue)
return null;
const formGroup = createTypedControls(defaultValue, options);
const controlValueProxyHandler = {
get: (target, prop) => {
if (target[prop] === undefined)
return undefined;
if (prop != FORM_GROUP_PROP) {
if (Array.isArray(target[prop])) {
return formGroup.get(prop);
}
else if (_isObject(target[prop])) {
return new Proxy(target[prop], controlValueProxyHandler);
}
return formGroup.get(prop);
}
return target[prop];
},
set: (target, prop, value) => {
if (prop !== FORM_GROUP_PROP) {
if (prop === VALUE_PROP) {
updateTypedFormControls(formGroup, value, options);
}
else {
updateTypedFormControls(formGroup.get(prop), value, options);
}
}
else {
target[prop] = value;
}
return true;
},
};
const formBuilder = new Proxy({
value: defaultValue,
}, controlValueProxyHandler);
formBuilder.formGroup = formGroup;
return formBuilder;
}
const TYPED_FORM_BUILDER = new InjectionToken('TYPED_FORM_BUILDER');
function forEach(elements, callback, returnIf) {
let result = true;
const length = elements.length;
for (let index = 0; index < length; index++) {
result = callback(elements[index], index);
if (!!returnIf && returnIf(result)) {
return result;
}
}
if (returnIf) {
return result;
}
return false;
}
function deepEquals(objectA, objectB) {
if ((objectA === null || objectA === undefined) &&
(objectB === null || objectB === undefined))
return true;
if (!objectA || !objectB)
return false;
if (typeof objectA !== 'object' && typeof objectB !== 'object') {
return objectA === objectB;
}
if (Array.isArray(objectA) && Array.isArray(objectB)) {
if (objectA.length !== objectB.length)
return false;
return forEach(objectA, function (elementA, index) {
return deepEquals(elementA, objectB[index]);
}, function (result) {
return !result;
});
}
if (typeof objectA === 'object' && typeof objectB === 'object') {
if (Object.keys(objectA).length === 0 && Object.keys(objectA).length === 0)
return true;
return forEach(Object.keys(objectA), function (objectAKey) {
if (typeof objectB[objectAKey] !== undefined) {
return deepEquals(objectA[objectAKey], objectB[objectAKey]);
}
return false;
}, function (result) {
return !result;
});
}
return false;
}
/**
* Generated bundle index. Do not edit.
*/
export { TYPED_FORM_BUILDER, typedFormBuilderFactory };
//# sourceMappingURL=developerwellness-angular-typed-forms.mjs.map