UNPKG

@datorama/akita-ng-forms-manager

Version:

The best way to manage your Angular form state in Akita

334 lines 15 kB
import * as tslib_1 from "tslib"; import { Injectable, Inject, Optional } from '@angular/core'; import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { coerceArray, filterNil, logAction } from '@datorama/akita'; import { merge } from 'rxjs'; import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'; import { FormsQuery } from './forms-manager.query'; import { FormsStore } from './forms-manager.store'; import { FORMS_MANAGER_OPTIONS, defaultOptions } from './forms-manager-options'; import * as i0 from "@angular/core"; import * as i1 from "./forms-manager-options"; var AkitaNgFormsManager = /** @class */ (function () { function AkitaNgFormsManager(options) { if (options === void 0) { options = {}; } this.valueChanges = {}; this.ngForms = {}; this._options = Object.assign({}, defaultOptions, options); this._store = new FormsStore({}); this._query = new FormsQuery(this.store); } Object.defineProperty(AkitaNgFormsManager.prototype, "query", { get: function () { return this._query; }, enumerable: true, configurable: true }); Object.defineProperty(AkitaNgFormsManager.prototype, "store", { get: function () { return this._store; }, enumerable: true, configurable: true }); AkitaNgFormsManager.prototype.selectValid = function (formName, path) { return this.selectControl(formName, path).pipe(map(function (control) { return control.valid; })); }; AkitaNgFormsManager.prototype.selectDirty = function (formName, path) { return this.selectControl(formName, path).pipe(map(function (control) { return control.dirty; })); }; AkitaNgFormsManager.prototype.selectDisabled = function (formName, path) { return this.selectControl(formName, path).pipe(map(function (control) { return control.disabled; })); }; AkitaNgFormsManager.prototype.selectValue = function (formName, path) { return this.selectControl(formName, path).pipe(map(function (control) { return control.value; })); }; AkitaNgFormsManager.prototype.selectErrors = function (formName, path) { return this.selectControl(formName, path).pipe(map(function (control) { return control.errors; })); }; AkitaNgFormsManager.prototype.selectNgForm = function (formName) { var _this = this; return this.selectForm(formName, { filterNil: true }).pipe(map(function () { return _this.ngForms[formName]; })); }; /** * If no path specified it means that it's a single FormControl or FormArray */ AkitaNgFormsManager.prototype.selectControl = function (formName, path) { var _this = this; if (!path) { return this.selectForm(formName); } return this.query .select(function (state) { return state[formName]; }) .pipe(filterNil, map(function (form) { return _this.resolveControl(form, path); }), distinctUntilChanged(function (a, b) { return JSON.stringify(a) === JSON.stringify(b); })); }; AkitaNgFormsManager.prototype.getControl = function (formName, path) { if (!path) { return this.getForm(formName); } if (this.hasForm(formName)) { var form = this.getForm(formName); return this.resolveControl(form, path); } return null; }; AkitaNgFormsManager.prototype.selectForm = function (formName, options) { if (options === void 0) { options = { filterNil: true }; } return this.query.select(function (state) { return state[formName]; }).pipe(options.filterNil ? filterNil : function (s) { return s; }); }; AkitaNgFormsManager.prototype.getForm = function (formName) { return this.query.getValue()[formName]; }; AkitaNgFormsManager.prototype.getNgForm = function (formName) { return this.ngForms[formName]; }; AkitaNgFormsManager.prototype.hasForm = function (formName) { return !!this.getForm(formName); }; AkitaNgFormsManager.prototype.upsert = function (formName, form, config) { var _this = this; if (config === void 0) { config = {}; } var merged = tslib_1.__assign({ debounceTime: this._options.debounceTime, emitEvent: false }, config); /** If the form already exist, patch the form with the store value */ if (this.hasForm(formName) === true) { form.patchValue(this.resolveStoreToForm(formName, form, merged.arrControlFactory), { emitEvent: merged.emitEvent }); } else { /** else update the store with the current form state */ this.updateStore(formName, form, true); if (merged.persistForm) { this.storeFormInstance(formName, form); } } this.valueChanges[formName] = merge(form.valueChanges, form.statusChanges.pipe(distinctUntilChanged())) .pipe(debounceTime(merged.debounceTime)) .subscribe(function () { return _this.updateStore(formName, form); }); return this; }; AkitaNgFormsManager.prototype.remove = function (formName) { var e_1, _a; if (formName) { this.removeFromStore(formName); } else { var availableForms = Object.keys(this.query.getValue()); try { for (var availableForms_1 = tslib_1.__values(availableForms), availableForms_1_1 = availableForms_1.next(); !availableForms_1_1.done; availableForms_1_1 = availableForms_1.next()) { var name_1 = availableForms_1_1.value; this.removeFromStore(name_1); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (availableForms_1_1 && !availableForms_1_1.done && (_a = availableForms_1.return)) _a.call(availableForms_1); } finally { if (e_1) throw e_1.error; } } } this.unsubscribe(formName); }; AkitaNgFormsManager.prototype.unsubscribe = function (formName, config) { var _this = this; if (config === void 0) { config = {}; } var e_2, _a; var _config = tslib_1.__assign({ removeNgForm: true }, { updateStore: this._options.updateStoreOnUnsubscribe }, config); var _formName = formName; var removeInstance = function (name) { return (_config.removeNgForm ? _this.removeFormInstance(name) : null); }; if (_formName) { if (this.valueChanges[_formName]) { this.valueChanges[_formName].unsubscribe(); delete this.valueChanges[_formName]; if (config.updateStore && this.ngForms[_formName]) { this.updateStore(_formName, this.getNgForm(_formName)); } removeInstance(_formName); } } else { try { for (var _b = tslib_1.__values(Object.keys(this.valueChanges)), _c = _b.next(); !_c.done; _c = _b.next()) { var name_2 = _c.value; this.valueChanges[name_2].unsubscribe(); if (config.updateStore && this.ngForms[name_2]) { this.updateStore(name_2, this.getNgForm(name_2)); } removeInstance(name_2); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } this.valueChanges = {}; } }; AkitaNgFormsManager.prototype.removeFromStore = function (formName) { var snapshot = this.query.getValue(); var newState = Object.keys(snapshot).reduce(function (acc, currentFormName) { if (formName !== currentFormName) { acc[currentFormName] = snapshot[currentFormName]; } return acc; }, {}); logAction("Remove " + formName); this.store._setState(function () { return newState; }); }; AkitaNgFormsManager.prototype.resolveControl = function (form, path) { var _a = tslib_1.__read(path.split('.')), first = _a[0], rest = _a.slice(1); if (rest.length === 0) { return form.controls[first]; } return this.find(form.controls[first], rest); }; AkitaNgFormsManager.prototype.find = function (control, path) { return path.reduce(function (current, name) { return current.controls.hasOwnProperty(name) ? current.controls[name] : null; }, control); }; AkitaNgFormsManager.prototype.resolveStoreToForm = function (formName, control, arrControlFactory) { var form = this.getForm(formName); var value = form.value; /** It means it a single control */ if (!form.controls) { return value; } this.handleFormArray(value, control, arrControlFactory); return value; }; AkitaNgFormsManager.prototype.handleFormArray = function (formValue, control, arrControlFactory) { var _this = this; if (control instanceof FormArray) { this.cleanArray(control); if (!arrControlFactory) { throw new Error('Please provide arrControlFactory'); } formValue.forEach(function (v, i) { return control.insert(i, arrControlFactory(v)); }); } else { Object.keys(formValue).forEach(function (controlName) { var value = formValue[controlName]; if (Array.isArray(value) && control.get(controlName) instanceof FormArray === true) { if (!arrControlFactory || (arrControlFactory && controlName in arrControlFactory === false)) { throw new Error('Please provide arrControlFactory for ' + controlName); } var current_1 = control.get(controlName); var fc_1 = arrControlFactory[controlName]; _this.cleanArray(current_1); value.forEach(function (v, i) { return current_1.insert(i, fc_1(v)); }); } }); } }; AkitaNgFormsManager.prototype.cleanArray = function (control) { while (control.length !== 0) { control.removeAt(0); } }; AkitaNgFormsManager.prototype.buildFormStoreState = function (formName, form) { var e_3, _a; var value; if (form instanceof FormControl) { value = this.resolveFormToStore(form); } if (form instanceof FormGroup || form instanceof FormArray) { // The root form group value = tslib_1.__assign({}, this.resolveFormToStore(form), { controls: {} }); try { for (var _b = tslib_1.__values(Object.keys(form.controls)), _c = _b.next(); !_c.done; _c = _b.next()) { var key = _c.value; var control = form.controls[key]; if (control instanceof FormGroup || form instanceof FormArray) { value.controls[key] = this.buildFormStoreState(formName, control); } else { value.controls[key] = this.resolveFormToStore(control); } } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_3) throw e_3.error; } } } return value; }; AkitaNgFormsManager.prototype.updateStore = function (formName, form, initial) { if (initial === void 0) { initial = false; } var _a; var value = this.buildFormStoreState(formName, form); var capitalized = formName[0].toUpperCase() + formName.slice(1); var action = (initial ? 'Create' : 'Update') + " " + capitalized + " Form"; logAction(action); this.store.update((_a = {}, _a[formName] = value, _a)); }; AkitaNgFormsManager.prototype.resolveFormToStore = function (control) { return { value: this.cloneValue(control.value), rawValue: control.getRawValue ? control.getRawValue() : null, valid: control.valid, dirty: control.dirty, invalid: control.invalid, disabled: control.disabled, errors: control.errors, touched: control.touched, pristine: control.pristine, pending: control.pending }; }; AkitaNgFormsManager.prototype.cloneValue = function (value) { return this.isObject(value) ? tslib_1.__assign({}, value) : Array.isArray(value) ? tslib_1.__spread(value) : value; }; AkitaNgFormsManager.prototype.isObject = function (val) { if (val == null) { return false; } if (Array.isArray(val)) { return false; } return typeof val === 'function' || typeof val === 'object'; }; AkitaNgFormsManager.prototype.storeFormInstance = function (formName, form) { var _a; var newForms = tslib_1.__assign({}, this.ngForms, (_a = {}, _a[formName] = form, _a)); this.ngForms = newForms; }; AkitaNgFormsManager.prototype.removeFormInstance = function (formName) { if (this.ngForms[formName]) { delete this.ngForms[formName]; } }; AkitaNgFormsManager.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FORMS_MANAGER_OPTIONS,] }] } ]; }; AkitaNgFormsManager.ɵprov = i0.ɵɵdefineInjectable({ factory: function AkitaNgFormsManager_Factory() { return new AkitaNgFormsManager(i0.ɵɵinject(i1.FORMS_MANAGER_OPTIONS, 8)); }, token: AkitaNgFormsManager, providedIn: "root" }); AkitaNgFormsManager = tslib_1.__decorate([ Injectable({ providedIn: 'root' }), tslib_1.__param(0, Optional()), tslib_1.__param(0, Inject(FORMS_MANAGER_OPTIONS)), tslib_1.__metadata("design:paramtypes", [Object]) ], AkitaNgFormsManager); return AkitaNgFormsManager; }()); export { AkitaNgFormsManager }; export function setValidators(control, validator) { control.setValidators(coerceArray(validator)); control.updateValueAndValidity(); } export function setAsyncValidators(control, validator) { control.setValidators(coerceArray(validator)); control.updateValueAndValidity(); } //# sourceMappingURL=forms-manager.js.map