import { Observable } from 'rxjs'; import { map, take } from 'rxjs/operators'; import path from 'ramda/src/path'; import flatten from 'ramda/src/flatten'; import uniq from 'ramda/src/uniq'; // import mergeDeepRight from 'ramda/src/mergeDeepRight'; // import assocPath from 'ramda/src/assocPath'; import { FormGroup, FormControl, FormBuilder, FormArray, AbstractControl } from "react-reactive-form"; type ErrorType = 'required' | 'email' | 'min' | 'max'; export class BigFormService { bigForm: FormGroup; private _errorMessages = {}; bigFormErrors = {}; constructor(private store) { this.bigForm = new FormGroup({}); this.initForm(); // if (!environment.production) { // this.bigForm.valueChanges.subscribe(form => console.log({ BIGFORM: form, FormModel: this.bigForm })); // } } initForm() { if (!this.bigForm) { this.bigForm = new FormGroup({}); } } get errorMessages() { return this._errorMessages; } addErrorMessage(controlName: string, errorType: ErrorType, message: string) { this._errorMessages[`${controlName}:${errorType}`] = message; } addSimpleValueToFormModel(controlName: string, value: any) { if (!this.bigForm.get(controlName)) { this.bigForm.addControl(controlName, new FormControl(value)); } } addObjectToFormModel(controlName: string, obj: any) { if (!this.bigForm.get(controlName)) { if (obj) { this.bigForm.addControl(controlName, FormBuilder.group(obj)); } } } patchToForm(sourceObservable: Observable, fieldMaps: { [key: string]: string }) { return sourceObservable.pipe( map(sourceObj => { Object.entries(fieldMaps).forEach(([key, value]) => { if (key && value) { let control = this.getControl(value); if (control) { control.setValue(this.getSourceValue(sourceObj, key)); } else { this.setControl(value); control = this.getControl(value); control.setValue(this.getSourceValue(sourceObj, key)); } } }); }) ); } getSourceValue(source, fieldPath: string) { const thePath = fieldPath.split('.'); return path(thePath, source) || ''; } patchValues(formValues: { [key: string]: any }) { Object.entries(formValues).forEach(([key, value]) => { if (!this.bigForm.get(key)) { if (typeof value === 'object' && value !== null && !Array.isArray(value)) { this.bigForm.addControl(key, FormBuilder.group(value)); } else if (Array.isArray(value)) { if (value.some(val => typeof val === 'function' || Array.isArray(val))) { // Then it contains a validation function this.bigForm.addControl(key, FormBuilder.control(value[0], value[1])); } else { this.bigForm.addControl(key, FormBuilder.control(value[0])); } } else { this.bigForm.addControl(key, FormBuilder.control(value)); } } else { this.bigForm.patchValue({ [key]: value }); } }); } addControls(formValues: { [key: string]: any }) { Object.entries(formValues).forEach(([key, value]) => { if (typeof value === 'object' && value !== null && !Array.isArray(value)) { this.bigForm.addControl(key, FormBuilder.group(value)); } else { this.bigForm.addControl(key, FormBuilder.control(value)); } }); } addControl(controlName: string, control: AbstractControl) { if (!this.bigForm.get(controlName)) { this.bigForm.addControl(controlName, control); } } getControl(controlPath: string) { this.initForm(); const path = controlPath.split('.'); let control = this.bigForm.controls[path[0]]; if (!control) { this.setControl(controlPath); control = this.bigForm.controls[path[0]]; } if (path.length > 1) { for (let i = 1; i < path.length; i++) { control = control.get(path[i]); } } return control; } getControlForValidation(controlPath: string) { this.initForm(); const path = controlPath.split('.'); let control = this.bigForm.controls[path[0]]; // if (!control) { // this.setControl(controlPath); // control = this.bigForm.controls[path[0]]; // } if (path.length > 1) { for (let i = 1; i < path.length; i++) { control = control.get(path[i]); } } return control; } setControl(controlPath: string) { const path = controlPath.split('.'); if (path.length === 1) { this.bigForm.addControl(path[0], new FormControl(null)); } else if (path.length === 2) { if (this.bigForm.get(path[0])) { (this.bigForm.get(path[0]) as FormGroup).addControl(path[1], new FormControl(null)); } else { this.bigForm.addControl(path[0], new FormGroup({ [path[1]]: new FormControl(null) })); } } } // bigFormToStoreMapper(mapper: { [id: string]: string | any[] }) { // return this.bigForm.valueChanges.pipe( // debounceTime(800), // map(formValues => { // return Object.entries(mapper).reduce((acc, [formPath, storePath]) => { // const valueExists = // path(formPath.split('.'), formValues) !== undefined && path(formPath.split('.'), formValues) !== null; // if (typeof storePath === 'string') { // return valueExists // ? mergeDeepRight(acc, assocPath(storePath.split('.'), path(formPath.split('.'), formValues), {})) // : acc; // } else if (Array.isArray(storePath) && typeof storePath[0] === 'string') { // return storePath.reduce((innerAcc, innerStorePath) => { // const innerObj = valueExists // ? mergeDeepRight( // innerAcc, // assocPath(innerStorePath.split('.'), path(formPath.split('.'), formValues), {}) // ) // : innerAcc; // return mergeDeepRight(acc, innerObj); // }, {}); // } else if (Array.isArray(storePath) && typeof storePath[0] === 'function') { // const [func, pathToStore] = storePath; // const transformed = func(path(formPath.split('.'), formValues)); // return valueExists ? mergeDeepRight(acc, assocPath(pathToStore.split('.'), transformed, {})) : acc; // } else if (Array.isArray(storePath) && Array.isArray(storePath[0])) { // return storePath.reduce((inner1, funcToPathArray) => { // const [func, pathToStore] = funcToPathArray; // const transformed = func( // path(formPath.split('.'), formValues)); // const innerObj = valueExists // ? mergeDeepRight(inner1, assocPath(pathToStore.split('.'), transformed, {})) // : inner1; // // const innerObj1 = valueExists // // ? R.mergeDeepRight(inner1, R.assocPath(pathToStore.split('.'), R.path(formPath.split('.'), formValues), {})) // // : inner1; // return mergeDeepRight(acc, innerObj); // }, {}); // } // }, {}); // }) // ); // } // allValid() { // this.bigForm.updateValueAndValidity(); // return this.bigForm.valueChanges.pipe(map(val => this.bigForm.valid)); // } // fieldsValid(fieldPaths: string[]) { // const watchedControls = fieldPaths.map(field => this.getControl(field)); // return combineLatest( // ...watchedControls.map(control => { // control.updateValueAndValidity(); // return control.valueChanges.pipe(map(val => control.valid)); // }) // ).pipe(map(res => res.every(val => val === true))); // } getFormGroupErrors(form: FormGroup | FormArray) { if (Array.isArray(form.controls)) { return form.controls .map((ctrl, key) => { const control = form.get(`${key}`); if (control instanceof FormControl) { const controlErrors = control.errors; if (controlErrors) { return Object.keys(controlErrors).map(keyError => { return `${key}:${keyError}`; }); } } else if (control instanceof FormGroup || control instanceof FormArray) { return this.getFormGroupErrors(control); } }) .filter(val => !!val) .map(data => flatten(data)); } else { return Object.keys(form.controls) .map(key => { const control = form.get(key); if (control instanceof FormControl) { const controlErrors = control.errors; if (controlErrors) { return Object.keys(controlErrors).map(keyError => { return `${key}:${keyError}`; }); } } else if (control instanceof FormGroup || control instanceof FormArray) { return this.getFormGroupErrors(control); } }) .filter(val => !!val) .map(data => flatten(data)); } } getErrorMessagesForDisplay(errorMessages: { [key: string]: string }) { const formGroupErrors = flatten(this.getFormGroupErrors(this.bigForm)); const errors = formGroupErrors.map(key => { return key && errorMessages && errorMessages[key]; }); return uniq(flatten(errors.filter(val => !!val))); } retrieveErrors$() { // return this.store.query('manifest.activeManifestItem').pipe( // take(1), // map(item => item && item.flowErrorMessages), // map(errorMessages => { // return this.getErrorMessagesForDisplay(errorMessages); // }) // ); } }