File

libs/acl/form-support/src/lib/binding/auto-form-binding.ts

Description

merge control finding with a given map of controls

Index

Properties

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;
  };

results matching ""

    No results matching ""