### File

`src/lib/form-array.ts`

### Extends

`UntypedFormArray`

### Implements

`AbstractControl`

### Index

###### Properties

- Public Readonly controlId
- Public controls
- Public Readonly dirty$
- Public Readonly disabled$
- Public Readonly enabled$
- Public Readonly errors
- Public Readonly errors$
- Public Readonly status
- Public Readonly status$
- Public Readonly statusChanges
- Public Readonly touch$
- Public Readonly value
- Public Readonly value$
- Public Readonly valueChanges

###### Methods

- Public at
- Public disabledWhile
- Public enabledWhile
- Public getError
- Public getRawValue
- Public hasError
- Public hasErrorAndDirty
- Public hasErrorAndTouched
- Public insert
- Public insertAt
- Public markAllAsDirty
- Public markAllAsPristine
- Public markAllAsUntouched
- Public markAsDirty
- Public markAsPristine
- Public markAsTouched
- Public markAsUntouched
- Public mergeAsyncValidators
- Public mergeValidators
- Public patchValue
- Public push
- Public removeAt
- Public reset
- Public select
- Public setAsyncValidators
- Public setControl
- Public setDisable
- Public setEnable
- Public setErrors
- Public setValidators
- Public setValue
- Public validateOn

###### Accessors

- readonly
- controlPath
- fullControlPath

### Constructor

`constructor(controls: Array<AbstractControl<T>>, options: FormArrayOptions)`
Defined in src/lib/form-array.ts:129

Parameters :

Name | Type | Optional
controls | `Array<AbstractControl<T>>` | No
options | `FormArrayOptions` | No

### Properties

Public Readonly controlId
Type : `string`
Defined in src/lib/form-array.ts:118

Public controls
Type : `Array<AbstractControl<T>>`
Defined in src/lib/form-array.ts:132

Public Readonly dirty$
Default value : `this.dirtyChanges .asObservable() .pipe(distinctUntilChanged())`
Defined in src/lib/form-array.ts:124

Public Readonly disabled$
Default value : `controlDisabled$(this)`
Defined in src/lib/form-array.ts:112

Public Readonly enabled$
Default value : `controlEnabled$(this)`
Defined in src/lib/form-array.ts:114

Public Readonly errors
Type : `E | null`
Defined in src/lib/form-array.ts:115

Public Readonly errors$
Default value : `controlErrorChanges$<E>(this)`
Defined in src/lib/form-array.ts:117

Public Readonly status
Type : `ControlState`
Defined in src/lib/form-array.ts:111

Public Readonly status$
Default value : `controlStatusChanges$(this)`
Defined in src/lib/form-array.ts:116

Public Readonly statusChanges
Type : `Observable<ControlState>`
Defined in src/lib/form-array.ts:113

Public Readonly touch$
Default value : `this.touchChanges .asObservable() .pipe(distinctUntilChanged())`
Defined in src/lib/form-array.ts:120

Public Readonly value
Type : `T[]`
Defined in src/lib/form-array.ts:95

Public Readonly value$
Default value : `controlValueChanges$<T[]>(this)`
Defined in src/lib/form-array.ts:109

Public Readonly valueChanges
Type : `Observable<T[]>`
Defined in src/lib/form-array.ts:107

### Methods

Public at
`at(index: number)`
Defined in src/lib/form-array.ts:146

Parameters :

Name | Type | Optional
index | `number` | No

Returns : `AbstractControl<T>`

Public disabledWhile
`disabledWhile(observable: Observable<boolean>, options?: ControlOptions)`
Defined in src/lib/form-array.ts:193

Parameters :

Name | Type | Optional
observable | `Observable<boolean>` | No
options | `ControlOptions` | Yes

Returns : `any`

Public enabledWhile
`enabledWhile(observable: Observable<boolean>, options?: ControlOptions)`
Defined in src/lib/form-array.ts:200

Parameters :

Name | Type | Optional
observable | `Observable<boolean>` | No
options | `ControlOptions` | Yes

Returns : `any`

Public getError
`getError(errorCode: K, path?: ControlPath)`
Defined in src/lib/form-array.ts:392

Type parameters :

- K

Parameters :

Name | Type | Optional
errorCode | `K` | No
path | `ControlPath` | Yes

Returns : `E[K]`

Public getRawValue
`getRawValue()`
Defined in src/lib/form-array.ts:150
Returns : `T[]`

Public hasError
`hasError(errorCode: ExtractStrings<E>, path?: ControlPath)`
Defined in src/lib/form-array.ts:384

Parameters :

Name | Type | Optional
errorCode | `ExtractStrings<E>` | No
path | `ControlPath` | Yes

Returns : `any`

Public hasErrorAndDirty
`hasErrorAndDirty(errorCode: ExtractStrings<E>, path?: ControlPath)`
Defined in src/lib/form-array.ts:303

Parameters :

Name | Type | Optional
errorCode | `ExtractStrings<E>` | No
path | `ControlPath` | Yes

Returns : `boolean`

Public hasErrorAndTouched
`hasErrorAndTouched(errorCode: ExtractStrings<E>, path?: ControlPath)`
Defined in src/lib/form-array.ts:251

Parameters :

Name | Type | Optional
errorCode | `ExtractStrings<E>` | No
path | `ControlPath` | Yes

Returns : `boolean`

Public insert
`insert(index: number, control: AbstractControl<T>)`
Defined in src/lib/form-array.ts:154

Parameters :

Name | Type | Optional
index | `number` | No
control | `AbstractControl<T>` | No

Returns : `void`

Public insertAt
`insertAt(index?: number, state?: T, options?: ControlEventOptions)`
Defined in src/lib/form-array.ts:169

inserts a new control at the specified index. If the index is undefined the new control will be added to the end.

Parameters :

Name | Type | Optional | Description
index | `number` | Yes | (optional) the index where the control should be created
state | `T` | Yes | (optional) the initial state of the new control
options | `ControlEventOptions` | Yes | (optional) ControlEventOptions

Returns : `void`

Public markAllAsDirty
`markAllAsDirty()`
Defined in src/lib/form-array.ts:219
Returns : `void`

Public markAllAsPristine
`markAllAsPristine()`
Defined in src/lib/form-array.ts:223
Returns : `void`

Public markAllAsUntouched
`markAllAsUntouched()`
Defined in src/lib/form-array.ts:241
Returns : `void`

Public markAsDirty
`markAsDirty(opts?: OnlySelf)`
Defined in src/lib/form-array.ts:355

Parameters :

Name | Type | Optional
opts | `OnlySelf` | Yes

Returns : `void`

Public markAsPristine
`markAsPristine(opts?: OnlySelf)`
Defined in src/lib/form-array.ts:350

Parameters :

Name | Type | Optional
opts | `OnlySelf` | Yes

Returns : `void`

Public markAsTouched
`markAsTouched(opts?: OnlySelf)`
Defined in src/lib/form-array.ts:340

Parameters :

Name | Type | Optional
opts | `OnlySelf` | Yes

Returns : `void`

Public markAsUntouched
`markAsUntouched(opts?: OnlySelf)`
Defined in src/lib/form-array.ts:345

Parameters :

Name | Type | Optional
opts | `OnlySelf` | Yes

Returns : `void`

Public mergeAsyncValidators
`mergeAsyncValidators(validators: AsyncValidator)`
Defined in src/lib/form-array.ts:211

Parameters :

Name | Type | Optional
validators | `AsyncValidator` | No

Returns : `void`

Public mergeValidators
`mergeValidators(validators: Validator)`
Defined in src/lib/form-array.ts:207

Parameters :

Name | Type | Optional
validators | `Validator` | No

Returns : `void`

Public patchValue
`patchValue(valueOrObservable: any, options?: ControlEventOptions)`
Defined in src/lib/form-array.ts:290

Parameters :

Name | Type | Optional
valueOrObservable | `any` | No
options | `ControlEventOptions` | Yes

Returns : `Subscription | void`

Public push
`push(control: AbstractControl<T>, options?: ControlEventOptions)`
Defined in src/lib/form-array.ts:322

Parameters :

Name | Type | Optional
control | `AbstractControl<T>` | No
options | `ControlEventOptions` | Yes

Returns : `void`

Public removeAt
`removeAt(index: number)`
Defined in src/lib/form-array.ts:310

Parameters :

Name | Type | Optional
index | `number` | No

Returns : `void`

Public reset
`reset(value?: T[], options?: ControlEventOptions)`
Defined in src/lib/form-array.ts:360

Parameters :

Name | Type | Optional
value | `T[]` | Yes
options | `ControlEventOptions` | Yes

Returns : `void`

Public select
`select(mapFn: (state: T[]) => void)`
Defined in src/lib/form-array.ts:142

Type parameters :

- R

Parameters :

Name | Type | Optional
mapFn | `function` | No

Returns : `Observable<R>`

Public setAsyncValidators
`setAsyncValidators(newValidator: AsyncValidator, updateValueAndValidity)`
Defined in src/lib/form-array.ts:374

Parameters :

Name | Type | Optional | Default value
newValidator | `AsyncValidator` | No |
updateValueAndValidity |  | No | `true`

Returns : `void`

Public setControl
`setControl(index: number, control: AbstractControl<T>, options?: ControlEventOptions)`
Defined in src/lib/form-array.ts:333

Parameters :

Name | Type | Optional
index | `number` | No
control | `AbstractControl<T>` | No
options | `ControlEventOptions` | Yes

Returns : `void`

Public setDisable
`setDisable(disable, opts?: ControlEventOptions)`
Defined in src/lib/form-array.ts:329

Parameters :

Name | Type | Optional | Default value
disable |  | No | `true`
opts | `ControlEventOptions` | Yes |

Returns : `void`

Public setEnable
`setEnable(enable, opts?: ControlEventOptions)`
Defined in src/lib/form-array.ts:318

Parameters :

Name | Type | Optional | Default value
enable |  | No | `true`
opts | `ControlEventOptions` | Yes |

Returns : `void`

Public setErrors
`setErrors(errors: Partial<E> | null, opts: EmitEvent)`
Defined in src/lib/form-array.ts:388

Parameters :

Name | Type | Optional | Default value
errors | `Partial<E> | null` | No |
opts | `EmitEvent` | No | `{}`

Returns : `any`

Public setValidators
`setValidators(newValidator: Validator, updateValueAndValidity)`
Defined in src/lib/form-array.ts:364

Parameters :

Name | Type | Optional | Default value
newValidator | `Validator` | No |
updateValueAndValidity |  | No | `true`

Returns : `void`

Public setValue
`setValue(valueOrObservable: T[] | Observable<T[]>, options?: ControlEventOptions)`
Defined in src/lib/form-array.ts:227

Parameters :

Name | Type | Optional
valueOrObservable | `T[] | Observable<T[]>` | No
options | `ControlEventOptions` | Yes

Returns : `Subscription | void`

Public validateOn
`validateOn(observableValidation: Observable<null | object>)`
Defined in src/lib/form-array.ts:245

Parameters :

Name | Type | Optional
observableValidation | `Observable<null | object>` | No

Returns : `any`

### Accessors

readonly
get `readonly()`
Defined in src/lib/form-array.ts:63
set `readonly(value: boolean)`
Defined in src/lib/form-array.ts:67

Parameters :

Name | Type | Optional
value | `boolean` | No

Returns : `void`

controlPath
get `controlPath()`
Defined in src/lib/form-array.ts:81

fullControlPath
get `fullControlPath()`
Defined in src/lib/form-array.ts:97

    import {
      AbstractControl as NgAbstractControl,
      UntypedFormArray,
    } from '@angular/forms';
    import {
      AbstractControl,
      AsyncValidator,
      ControlEventOptions,
      ControlOptions,
      ControlPath,
      ControlState,
      EmitEvent,
      ExtractStrings,
      OnlySelf,
      Validator,
    } from './types';
    import {
      distinctUntilChanged,
      map,
    } from 'rxjs/operators';
    import {
      isObservable,
      Observable,
      Subject,
      Subscription,
    } from 'rxjs';
    import {
      controlDisabled$,
      controlDisabledWhile,
      controlEnabled$,
      controlEnabledWhile,
      controlErrorChanges$,
      controlStatusChanges$,
      controlValueChanges$,
      disableControl,
      enableControl,
      hasErrorAndDirty,
      hasErrorAndTouched,
      markAllDirty,
      markAllPristine,
      markAllUntouched,
      mergeControlValidators,
    } from './control-actions';
    import { coerceArray } from '@rxap/utilities';
    import {
      ControlInsertedFn,
      ControlRemovedFn,
      FormArrayOptions,
      FormBuilderFn,
      FormDefinition,
      FormType,
    } from './model';
    import { isDevMode } from '@angular/core';

    export class RxapFormArray<T = any,
      E extends object = any,
      Parent extends object = any>
      extends UntypedFormArray
      implements AbstractControl<T[]> {

      private _readonly = false;

      public get readonly(): boolean {
        return (this.parent as any)?.readonly ?? this._readonly;
      }

      public set readonly(value: boolean) {
        this._readonly = value;
        this.controls.forEach(control => (control as any).stateChanges?.next());
      }

      /**
       * @internal
       */
      public get rxapFormDefinition():
        | (FormType<Parent> & FormDefinition<Parent>)
        | undefined {
        return (this.parent as any).rxapFormDefinition;
      }

      public get controlPath(): string {
        const parent: any = this.parent;
        if (parent) {
          if (parent.controlPath) {
            if (parent === this.root) {
              return this.controlId;
            } else {
              return [ parent.controlPath, this.controlId ].join('.');
            }
          }
        }
        return this.controlId;
      }

      public override readonly value!: T[];

      public get fullControlPath(): string {
        const parent: any = this.parent;
        if (parent) {
          if (parent.fullControlPath) {
            return [ parent.fullControlPath, this.controlId ].join('.');
          }
        }
        return this.controlId;
      }

      public override readonly valueChanges!: Observable<T[]>;

      public readonly value$ = controlValueChanges$<T[]>(this);
      // @ts-expect-error overwrite the public type
      public override readonly status!: ControlState;
      public readonly disabled$ = controlDisabled$(this);
      public override readonly statusChanges!: Observable<ControlState>;
      public readonly enabled$ = controlEnabled$(this);
      public override readonly errors!: E | null;
      public readonly status$ = controlStatusChanges$(this);
      public readonly errors$ = controlErrorChanges$<E>(this);
      public readonly controlId: string;
      private readonly touchChanges = new Subject<boolean>();
      public readonly touch$ = this.touchChanges
                                   .asObservable()
                                   .pipe(distinctUntilChanged());
      private readonly dirtyChanges = new Subject<boolean>();
      public readonly dirty$ = this.dirtyChanges
                                   .asObservable()
                                   .pipe(distinctUntilChanged());
      private readonly _builder: FormBuilderFn;
      private readonly _controlInsertedFn: ControlInsertedFn;
      private readonly _controlRemovedFn: ControlRemovedFn;

      constructor(
        public override controls: Array<AbstractControl<T>>,
        options: FormArrayOptions,
      ) {
        super(controls, options);
        this.controlId = options.controlId;
        this._builder = options.builder;
        this._controlInsertedFn = options.controlInsertedFn;
        this._controlRemovedFn = options.controlRemovedFn;
      }

      public select<R>(mapFn: (state: T[]) => R): Observable<R> {
        return this.value$.pipe(map(mapFn), distinctUntilChanged());
      }

      public override at(index: number): AbstractControl<T> {
        return super.at(index) as AbstractControl<T>;
      }

      public override getRawValue(): T[] {
        return super.getRawValue();
      }

      public override insert(index: number, control: AbstractControl<T>): void {
        if (isDevMode()) {
          console.warn('It is not recommend to use the FormArray.insert method');
        }
        return super.insert(index, control);
      }

      /**
       * inserts a new control at the specified index. If the index is undefined
       * the new control will be added to the end.
       *
       * @param index (optional) the index where the control should be created
       * @param state (optional) the initial state of the new control
       * @param options (optional) ControlEventOptions
       */
      public insertAt(index?: number, state?: T, options?: ControlEventOptions): void {
        const insertIndex = index ?? this.controls.length;
        const controlOrDefinition = this._builder(state, {
          controlId: insertIndex.toFixed(0),
        });

        this._controlInsertedFn(insertIndex, controlOrDefinition);

        if (insertIndex < this.controls.length) {
          // update the control ids for all controls, that are moved.
          for (let i = insertIndex; i < this.controls.length; i++) {
            Reflect.set(this.controls[i], 'controlId', (i + 1).toFixed(0));
          }
        }

        // call the super insert after the update, bc the insert method will
        // trigger a change detection
        if (controlOrDefinition instanceof NgAbstractControl) {
          super.insert(insertIndex, controlOrDefinition, options);
        } else {
          super.insert(insertIndex, controlOrDefinition.rxapFormGroup!, options);
        }
      }

      public disabledWhile(
        observable: Observable<boolean>,
        options?: ControlOptions,
      ) {
        return controlDisabledWhile(this, observable, options);
      }

      public enabledWhile(
        observable: Observable<boolean>,
        options?: ControlOptions,
      ) {
        return controlEnabledWhile(this, observable, options);
      }

      public mergeValidators(validators: Validator) {
        mergeControlValidators(this, validators);
      }

      public mergeAsyncValidators(validators: AsyncValidator) {
        this.setAsyncValidators([
          ...coerceArray(this.asyncValidator),
          ...coerceArray(validators),
        ]);
        this.updateValueAndValidity();
      }

      public markAllAsDirty(): void {
        markAllDirty(this);
      }

      public markAllAsPristine(): void {
        markAllPristine(this);
      }

      public override setValue(
        valueOrObservable: T[] | Observable<T[]>,
        options?: ControlEventOptions,
      ): Subscription | void {
        if (isObservable(valueOrObservable)) {
          return valueOrObservable.subscribe((value) => {
              super.setValue(value, options);
            },
          );
        }

        super.setValue(valueOrObservable, options);
      }

      public markAllAsUntouched(): void {
        markAllUntouched(this);
      }

      public validateOn(observableValidation: Observable<null | object>) {
        return observableValidation.subscribe((maybeError) => {
          this.setErrors(maybeError);
        });
      }

      public hasErrorAndTouched(
        errorCode: ExtractStrings<E>,
        path?: ControlPath,
      ): boolean {
        return hasErrorAndTouched(this, errorCode, path);
      }

      private _patchValue(value: T[], options?: ControlEventOptions) {
        // Even though the `value` argument type doesn't allow `null` and `undefined` values, the
        // `patchValue` can be called recursively and inner data structures might have these values, so
        // we just ignore such cases when a field containing FormArray instance receives `null` or
        // `undefined` as a value.
        if (value == null /* both `null` and `undefined` */) {
          return;
        }
        if (options?.strict) {
          if (this.length > value.length) {
            for (let index = this.length - 1; index >= value.length; index--) {
              this.removeAt(index);
            }
          }
        }
        value.forEach((newValue, index) => {
          if (this.at(index)) {
            this.at(index)
                .patchValue(
                  newValue,
                  {
                    ...(options ?? {}),
                    onlySelf: true,
                  },
                );
          } else if (options?.coerce) {
            this.insertAt(index, value[index]);
          }
        });
        this.updateValueAndValidity(options);
      }

      public override patchValue(
        valueOrObservable: any,
        options?: ControlEventOptions,
      ): Subscription | void {
        if (isObservable(valueOrObservable)) {
          return (valueOrObservable as Observable<T[]>).subscribe((value: T[]) => {
            this._patchValue(value, options);
          });
        }

        this._patchValue(valueOrObservable as T[], options);
      }

      public hasErrorAndDirty(
        errorCode: ExtractStrings<E>,
        path?: ControlPath,
      ): boolean {
        return hasErrorAndDirty(this, errorCode, path);
      }

      public override removeAt(index: number) {
        if (isDevMode()) {
          console.warn('It is not recommend to use the FormArray.removeAt method');
        }
        super.removeAt(index);
        this._controlRemovedFn(index);
      }

      public setEnable(enable = true, opts?: ControlEventOptions) {
        enableControl(this, enable, opts);
      }

      public override push(control: AbstractControl<T>, options?: ControlEventOptions): void {
        if (isDevMode()) {
          console.warn('It is not recommend to use the FormArray.push method');
        }
        return super.push(control, options);
      }

      public setDisable(disable = true, opts?: ControlEventOptions) {
        disableControl(this, disable, opts);
      }

      public override setControl(index: number, control: AbstractControl<T>, options?: ControlEventOptions): void {
        if (isDevMode()) {
          console.warn('It is not recommend to use the FormArray.setControl method');
        }
        return super.setControl(index, control, options);
      }

      public override markAsTouched(opts?: OnlySelf): void {
        super.markAsTouched(opts);
        this.touchChanges.next(true);
      }

      public override markAsUntouched(opts?: OnlySelf): void {
        super.markAsUntouched(opts);
        this.touchChanges.next(false);
      }

      public override markAsPristine(opts?: OnlySelf): void {
        super.markAsPristine(opts);
        this.dirtyChanges.next(false);
      }

      public override markAsDirty(opts?: OnlySelf): void {
        super.markAsDirty(opts);
        this.dirtyChanges.next(true);
      }

      public override reset(value?: T[], options?: ControlEventOptions): void {
        super.reset(value, options);
      }

      public override setValidators(
        newValidator: Validator,
        updateValueAndValidity = true,
      ): void {
        super.setValidators(newValidator);
        if (updateValueAndValidity) {
          super.updateValueAndValidity();
        }
      }

      public override setAsyncValidators(
        newValidator: AsyncValidator,
        updateValueAndValidity = true,
      ): void {
        super.setAsyncValidators(newValidator);
        if (updateValueAndValidity) {
          super.updateValueAndValidity();
        }
      }

      public override hasError(errorCode: ExtractStrings<E>, path?: ControlPath) {
        return super.hasError(errorCode, path);
      }

      public override setErrors(errors: Partial<E> | null, opts: EmitEvent = {}) {
        return super.setErrors(errors, opts);
      }

      public override getError<K extends ExtractStrings<E>>(
        errorCode: K,
        path?: ControlPath,
      ) {
        return super.getError(errorCode, path) as E[K] | null;
      }
    }

# results matching ""

# No results matching ""