libs/acl/form-support/src/lib/binding/auto-form-binding.ts
merge control finding with a given map of controls
Properties |
excludes (Optional) | |
Type |
string[]
|
overrides (Optional) | |
Type |
AclMapItem[]
|
import { AclEvaluationInterface } from '@allianz/taly-acl';
import { FormGroup } from '@angular/forms';
import { BehaviorSubject, mergeAll, Observable, ReplaySubject } from 'rxjs';
import { tap } from 'rxjs/operators';
import { AclMapItem } from '../../types';
import { clearAclReadOnlyValues } from '../data/clear-acl-read-only';
import { getAclPatchObject } from '../data/get-acl-path-object';
import { AclControlItem } from '../support/acl-control-item';
import { updateAclOnStructureChange } from '../support/update-acl-on-structure-change';
/**
* merge control finding with a given map of controls
*/
export interface AutoFormBindingFactoryParams {
overrides?: AclMapItem[];
excludes?: string[];
}
export interface FormBindingReturnValue {
stream$: Observable<boolean>;
clearAclReadOnlyValues: <T>(state: T) => T;
getPatchObject: <T>(state: T) => unknown;
}
export const autoFormBindingFactory =
(autoFormBindingFactoryParams: AutoFormBindingFactoryParams = {}) =>
(acl: AclEvaluationInterface, form: FormGroup): FormBindingReturnValue => {
if (!form) {
throw new Error(
'Trying to ACL-bind a malformed form. The given form is probably null or undefined.'
);
}
const newStream$ = new ReplaySubject<Observable<boolean>>();
const latestControlList$ = new BehaviorSubject<AclControlItem[]>([]);
updateAclOnStructureChange(
acl,
newStream$,
form,
latestControlList$,
autoFormBindingFactoryParams
);
form.valueChanges
.pipe(
tap(() => {
updateAclOnStructureChange(
acl,
newStream$,
form,
latestControlList$,
autoFormBindingFactoryParams
);
})
)
.subscribe();
const clearFn = <T extends Record<string, unknown>>(state: T) => {
const currentControlList = latestControlList$.value;
return clearAclReadOnlyValues(currentControlList, acl)(state);
};
const patchFn = <T extends Record<string, unknown>>(state: T) => {
const currentControlList = latestControlList$.value;
return getAclPatchObject(currentControlList, form, acl)(state);
};
return {
stream$: newStream$.pipe(mergeAll()),
clearAclReadOnlyValues: clearFn,
getPatchObject: patchFn
} as FormBindingReturnValue;
};