@ng-simplicity/forms-core 1.1.3 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- import * as rxjs from 'rxjs';
2
1
  import { Subject, Subscription, Observable, BehaviorSubject } from 'rxjs';
3
2
  import * as i0 from '@angular/core';
4
- import { OnInit, OnDestroy, Signal, Type, InjectionToken, Injector, ViewContainerRef, ChangeDetectorRef } from '@angular/core';
3
+ import { OnInit, OnDestroy, Signal, Type, InjectionToken, Injector, ViewContainerRef, ChangeDetectorRef, OnChanges, SimpleChanges } from '@angular/core';
5
4
  import * as _angular_forms from '@angular/forms';
6
- import { ValidatorFn, UntypedFormControl, FormGroup, AbstractControl, UntypedFormGroup, UntypedFormArray, FormArray } from '@angular/forms';
5
+ import { ValidatorFn, AbstractControl, UntypedFormControl, FormGroup, UntypedFormGroup, UntypedFormArray, FormArray } from '@angular/forms';
7
6
  import * as _ng_simplicity_forms_core from '@ng-simplicity/forms-core';
8
7
  import * as i1 from '@angular/common';
9
8
 
@@ -39,8 +38,8 @@ type NgsFormsFormErrorKeyValueMap = {
39
38
 
40
39
  /** One option of a radio group or select. */
41
40
  interface NgsFormsFormInputOption {
42
- /** Value written to the form control when the option is chosen. */
43
- id: string;
41
+ /** Value written to the form control when the option is chosen. Numbers stay numbers. */
42
+ id: string | number;
44
43
  /** Text shown to the user. */
45
44
  label: string;
46
45
  /** Renders the option but prevents choosing it. */
@@ -133,10 +132,7 @@ interface NgsFormsFormItemConfigBaseItemWithNameAndValidators extends NgsFormsFo
133
132
  validators?: Array<ValidatorFn>;
134
133
  /**
135
134
  * Stream of validator arrays. Each emission replaces the control's validators, which lets rules depend on other
136
- * values in the form. Ignored when `validators` is also set.
137
- *
138
- * @remarks The control's validity is recalculated on its next value change, so call `updateValueAndValidity()`
139
- * yourself if you need the new rules to apply immediately.
135
+ * values in the form. The control is re-validated on each emission. Ignored when `validators` is also set.
140
136
  */
141
137
  validators$?: Observable<Array<ValidatorFn>>;
142
138
  }
@@ -210,6 +206,8 @@ interface NgsFormsCommonComponentState {
210
206
  displayMode?: 'input' | 'summary';
211
207
  /** Whether to show a control that lets the user switch between `summary` and `input`. */
212
208
  showEditToggle?: boolean;
209
+ /** Your own keys. Read them from `commonState()` in custom components. */
210
+ [key: string]: unknown;
213
211
  }
214
212
 
215
213
  interface NgsFormsGlobalFormState extends NgsFormsCommonComponentState {
@@ -288,10 +286,14 @@ declare abstract class NgsFormsBaseClassFormComponent<T extends NgsFormsFormItem
288
286
  * Base class for items that own a form control. Creates the control (seeded with `value` when the config has one),
289
287
  * applies `validators` / `validators$` and `disabled` / `disabled$`, registers it with the parent group under
290
288
  * `config.name` and keeps `errorMessage` up to date.
289
+ *
290
+ * @typeParam T - The item's config type.
291
+ * @typeParam C - The type of `control`. Inputs use the default `UntypedFormControl`; groups and arrays set it in
292
+ * their constructor to an `UntypedFormGroup` or `UntypedFormArray`.
291
293
  */
292
- declare class NgsFormsFormItemWithVisibleAndValidatorsBase<T extends NgsFormsFormItemConfigBaseItemWithNameAndValidators> extends NgsFormsBaseClassFormComponent<T> implements OnInit, OnDestroy {
294
+ declare class NgsFormsFormItemWithVisibleAndValidatorsBase<T extends NgsFormsFormItemConfigBaseItemWithNameAndValidators, C extends AbstractControl = UntypedFormControl> extends NgsFormsBaseClassFormComponent<T> implements OnInit, OnDestroy {
293
295
  /** The item's form control. Bind it with `[formControl]`. */
294
- control: UntypedFormControl | undefined;
296
+ control: C | undefined;
295
297
  /**
296
298
  * Message for the control's first error, taken from `errorMessageMap`. Empty while the control is valid, or
297
299
  * before it is touched, dirty or submitted.
@@ -305,13 +307,15 @@ declare class NgsFormsFormItemWithVisibleAndValidatorsBase<T extends NgsFormsFor
305
307
  /** The latest value of `disabled` / `disabled$`, or `undefined` when the config sets neither. */
306
308
  private disabledFromConfig;
307
309
  ngOnInit(): void;
310
+ /** Whether the control currently has `Validators.required` or `Validators.requiredTrue`. */
311
+ get isRequired(): boolean;
308
312
  private updateErrorMessage;
309
313
  ngOnDestroy(): void;
310
314
  private bindValidators;
311
315
  private bindDisabled;
312
316
  private applyDisabled;
313
- static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormsFormItemWithVisibleAndValidatorsBase<any>, never>;
314
- static ɵdir: i0.ɵɵDirectiveDeclaration<NgsFormsFormItemWithVisibleAndValidatorsBase<any>, never, never, {}, {}, never, never, true, never>;
317
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormsFormItemWithVisibleAndValidatorsBase<any, any>, never>;
318
+ static ɵdir: i0.ɵɵDirectiveDeclaration<NgsFormsFormItemWithVisibleAndValidatorsBase<any, any>, never, never, {}, {}, never, never, true, never>;
315
319
  }
316
320
 
317
321
  /**
@@ -339,6 +343,84 @@ declare class NgsFormsComponentRegistryService {
339
343
  static ɵprov: i0.ɵɵInjectableDeclaration<NgsFormsComponentRegistryService>;
340
344
  }
341
345
 
346
+ /**
347
+ * Server errors for a form, in the same shape as the form value. Each leaf is the error key (or keys) to show on
348
+ * that control. The key is looked up in the control's `errorMessageMap`, just like a client-side validator's key.
349
+ *
350
+ * @example
351
+ * ```ts
352
+ * // Root group `registration`, its `userName` field taken, and the third row of the `contacts` array rejected.
353
+ * const errors: NgsFormsServerErrors = {
354
+ * registration: {
355
+ * userName: 'taken',
356
+ * contacts: [{}, {}, { phone: 'invalidPhone' }, {}],
357
+ * },
358
+ * };
359
+ * ```
360
+ */
361
+ type NgsFormsServerErrors = string | string[] | NgsFormsServerErrorGroup | NgsFormsServerErrorArray;
362
+ /** Server errors for the controls of a form group, keyed by control name. */
363
+ interface NgsFormsServerErrorGroup {
364
+ [controlName: string]: NgsFormsServerErrors | null | undefined;
365
+ }
366
+ /** Server errors for the rows of a form array, by row index. Use `{}` or `null` for a row without errors. */
367
+ type NgsFormsServerErrorArray = Array<NgsFormsServerErrors | null | undefined>;
368
+ /** One server error: the path of the control and the error key to show on it. */
369
+ interface NgsFormsServerErrorPath {
370
+ /**
371
+ * Path of the control in the form value, for example `registration.userName` or
372
+ * `registration.contacts[2].phone`. A leading `$` or `$.` is ignored, and bracket keys such as `['user name']`
373
+ * are allowed.
374
+ */
375
+ jsonPath: string;
376
+ /** The error key, looked up in the control's `errorMessageMap`. */
377
+ validator: string;
378
+ }
379
+ /**
380
+ * Builds the object for `NgsFormsService.setServerErrorMessages()` from a flat list of paths and error keys, for
381
+ * APIs that return their errors that way. Array indexes create arrays, and rows without errors are filled with `{}`.
382
+ * Two errors on the same path become an array of keys.
383
+ *
384
+ * @example
385
+ * ```ts
386
+ * constructServerErrorMessageObject([
387
+ * { jsonPath: 'registration.userName', validator: 'taken' },
388
+ * { jsonPath: 'registration.contacts[2].phone', validator: 'invalidPhone' },
389
+ * ]);
390
+ * // { registration: { userName: 'taken', contacts: [{}, {}, { phone: 'invalidPhone' }] } }
391
+ * ```
392
+ */
393
+ declare function constructServerErrorMessageObject(errors: ReadonlyArray<NgsFormsServerErrorPath>): NgsFormsServerErrorGroup;
394
+ /**
395
+ * Marker on the error value of a server error (`control.errors[key][NGS_FORMS_SERVER_ERROR] === true`). When the
396
+ * key has no entry in `errorMessageMap`, the key itself is shown as the message, so servers can send message text.
397
+ */
398
+ declare const NGS_FORMS_SERVER_ERROR = "ngsServerError";
399
+ /**
400
+ * Applies server errors to a form and clears each one when its control's value changes.
401
+ *
402
+ * @internal Used by `NgsFormsService`.
403
+ */
404
+ declare class NgsFormsServerErrorRegistry {
405
+ private readonly entries;
406
+ /**
407
+ * Validator that reports a control's server errors. Form items include it whenever they set their validators,
408
+ * so the errors survive re-validation until the control's value changes.
409
+ */
410
+ readonly validator: ValidatorFn;
411
+ /** `true` while at least one server error is set. */
412
+ get hasErrors(): boolean;
413
+ /** Replaces every server error with `errors`. Returns the paths that matched no control. */
414
+ set(root: AbstractControl, errors: NgsFormsServerErrors | null | undefined): string[];
415
+ /** Removes every server error. */
416
+ clear(): void;
417
+ /** Forgets every server error without re-validating, for when the controls are being thrown away. */
418
+ reset(): void;
419
+ private apply;
420
+ private applyKeys;
421
+ private validate;
422
+ }
423
+
342
424
  /**
343
425
  * Per form state holder that connects `<ngs-form>`, its items and `NgsFormsService`.
344
426
  *
@@ -352,19 +434,22 @@ declare class NgsFormsInternalService {
352
434
  state: BehaviorSubject<{
353
435
  [key: string]: any;
354
436
  }>;
437
+ /** Server errors set with `NgsFormsService.setServerErrorMessages()`. */
438
+ readonly serverErrors: NgsFormsServerErrorRegistry;
355
439
  setIsSubmitted(isSubmitted: boolean): void;
440
+ /** `true` when no rendered control fails its validators. A form whose controls are all disabled counts as valid. */
356
441
  checkIsValid(): boolean;
357
442
  setFormData(formConfig: NgsFormsFormConfig): void;
358
443
  private mergeState;
359
444
  /** Sets a component's state from its config's `initialState`, unless state for `uuid` already exists. */
360
445
  seedComponentState(uuid: string, initialState: any): void;
361
- updateGlobalState(state: NgsFormsGlobalFormState): void;
362
- updateComponentState(componentKey: string, state: any): void;
446
+ updateGlobalState(state: Partial<NgsFormsGlobalFormState>): void;
447
+ updateComponentState(componentKey: string, state: Partial<NgsFormsCommonComponentState>): void;
363
448
  /**
364
449
  * Merged state for one component: its own (by `uuid`), then by `name`, then global.
365
450
  * `initialState` seeds the component's own state unless state for `uuid` already exists.
366
451
  */
367
- subscribeToState(uuid: string, name?: string, initialState?: any): rxjs.Observable<any>;
452
+ subscribeToState(uuid: string, name?: string, initialState?: any): Observable<NgsFormsCommonComponentState>;
368
453
  static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormsInternalService, never>;
369
454
  static ɵprov: i0.ɵɵInjectableDeclaration<NgsFormsInternalService>;
370
455
  }
@@ -387,10 +472,6 @@ declare class NgsFormsInternalService {
387
472
  * ```
388
473
  */
389
474
  declare class NgsFormsService implements OnDestroy {
390
- /**
391
- * @internal
392
- */
393
- attempt: number;
394
475
  /**
395
476
  * Emits the root form group's value every time it changes. Combine with `toSignal()` to read it in a template.
396
477
  *
@@ -400,8 +481,20 @@ declare class NgsFormsService implements OnDestroy {
400
481
  /** The latest value emitted by `formValue$`. */
401
482
  formValue: any;
402
483
  private internalFormService;
403
- private formGroupSubscriptions;
484
+ private formGroupBinding;
404
485
  private formGroup;
486
+ /** The config from the latest `setFormConfig()` call, re-applied when `<ngs-form>` (re)connects. */
487
+ private lastConfig;
488
+ private missingFormTimer;
489
+ private destroyed;
490
+ /** Patches still being applied while the form renders, in call order. */
491
+ private pendingPatches;
492
+ private patchTimer;
493
+ /** The controls that existed when the pending patches were last applied. */
494
+ private patchedStructure;
495
+ private patchRounds;
496
+ /** Render passes in a row in which no control was added or removed. */
497
+ private stablePatchRounds;
405
498
  /** `true` once the user has changed any control in the form. */
406
499
  get dirty(): boolean;
407
500
  /** `true` when every rendered control passes its validators. Hidden items are not validated. */
@@ -411,14 +504,21 @@ declare class NgsFormsService implements OnDestroy {
411
504
  /**
412
505
  * Renders a form from `formConfig`, replacing any form that is already shown and resetting the submitted state.
413
506
  *
414
- * @remarks It is safe to call before `<ngs-form>` has initialised (for example in `ngOnInit`): the call is retried
415
- * every 25 ms for about half a second until the form component is available.
507
+ * @remarks It is safe to call before `<ngs-form>` has initialised (for example in `ngOnInit`): the latest config
508
+ * is kept and applied as soon as the form component connects, and also when it is destroyed and created again
509
+ * (inside an `@if` or a tab, for example). An error is logged if no form has connected after half a second.
416
510
  */
417
511
  setFormConfig(formConfig: NgsFormsFormConfig): void;
418
512
  /**
419
513
  * @internal
420
514
  */
421
515
  setInternalService(internalFormsService: NgsFormsInternalService): void;
516
+ /**
517
+ * @internal
518
+ * Disconnects `internalFormsService` when its `<ngs-form>` is destroyed. Does nothing if another form has
519
+ * connected since.
520
+ */
521
+ clearInternalService(internalFormsService: NgsFormsInternalService): void;
422
522
  /**
423
523
  * Marks the form as submitted (or not). While submitted, every invalid control shows its error message even if
424
524
  * the user never touched it.
@@ -429,17 +529,48 @@ declare class NgsFormsService implements OnDestroy {
429
529
  * Merges `state` into the state of one component, identified by its `uuid` or control `name`.
430
530
  * Components read the merged result through `commonState`.
431
531
  */
432
- updateComponentState(componentKey: string, state: any): void;
532
+ updateComponentState(componentKey: string, state: Partial<NgsFormsCommonComponentState>): void;
433
533
  /** Merges `state` into the state shared by every component in the form. */
434
- updateGlobalState(state: any): void;
534
+ updateGlobalState(state: Partial<NgsFormsGlobalFormState>): void;
435
535
  ngOnDestroy(): void;
536
+ /**
537
+ * Shows errors from the server on the matching controls, replacing any server errors shown before.
538
+ *
539
+ * @param errors - An object shaped like the form value (including the root group name) whose leaves are error
540
+ * keys, for example `{ registration: { userName: 'taken', contacts: [{}, {}, { phone: 'invalid' }] } }`. Each key
541
+ * is looked up in that control's `errorMessageMap`; when it has no entry the key itself is shown, so the server
542
+ * can also send the message text. Use `constructServerErrorMessageObject()` to build it from a list of paths.
543
+ * @returns The paths that matched no rendered control (a hidden item or a missing array row, for example), so you
544
+ * can show those errors elsewhere.
545
+ *
546
+ * @remarks The controls are marked as touched so the messages show at once, and they stay invalid until their
547
+ * value changes. All server errors are cleared by the next call, by `clearServerErrorMessages()`, by
548
+ * `setFormConfig()`, and when rows are added to or removed from a form array, because rows are matched by index.
549
+ */
550
+ setServerErrorMessages(errors: NgsFormsServerErrors): string[];
551
+ /** Removes every error set with `setServerErrorMessages()`. */
552
+ clearServerErrorMessages(): void;
436
553
  /**
437
554
  * Patches values into the form, using the same shape as `formValue$` (including the root group name).
438
555
  *
439
- * @remarks Only controls that are currently rendered receive values. Patch again after a conditional item becomes
440
- * visible, and make sure a form array has enough rows (see `initialItemCount`) before patching array values.
556
+ * @remarks It is safe to call straight after `setFormConfig()`, or before `<ngs-form>` has connected. The values
557
+ * are applied at once to the controls that exist, kept, and applied again each time new controls appear, until
558
+ * the form stops changing. That covers items that render later and items behind `visible$` that the patched values
559
+ * themselves reveal (and anything those reveal in turn). Later calls are applied after earlier ones. A form array
560
+ * only receives values for rows it has, so give it enough rows with `initialItemCount`. `setFormConfig()` drops
561
+ * patches that are still being applied to the previous form.
441
562
  */
442
563
  patchValue(entityData: any): void;
564
+ /** Maximum number of render passes a patch waits for new controls before it is dropped. */
565
+ private static readonly MAX_PATCH_ROUNDS;
566
+ private applyPendingPatches;
567
+ /**
568
+ * Waits one render pass, then re-applies the pending patches if controls were added or removed. Stops once two
569
+ * passes in a row change nothing (rendering can take a pass to start), or after `MAX_PATCH_ROUNDS` passes. Waits
570
+ * without counting while no form is connected.
571
+ */
572
+ private schedulePatchRound;
573
+ private cancelPendingPatches;
443
574
  static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormsService, never>;
444
575
  static ɵprov: i0.ɵɵInjectableDeclaration<NgsFormsService>;
445
576
  }
@@ -490,7 +621,7 @@ declare class NgsFormsBaseClassFormItemInputWithOptionsComponent<T extends NgsFo
490
621
  * <ngs-form></ngs-form>
491
622
  * ```
492
623
  */
493
- declare class NgsFormComponent {
624
+ declare class NgsFormComponent implements OnDestroy {
494
625
  private readonly ngsInternalFormsService;
495
626
  readonly ngsFormsService: NgsFormsService;
496
627
  readonly formGroup: i0.Signal<_angular_forms.FormGroup<any> | undefined>;
@@ -501,6 +632,7 @@ declare class NgsFormComponent {
501
632
  root: _ng_simplicity_forms_core.NgsFormsFormItem<any>;
502
633
  }[]>;
503
634
  constructor();
635
+ ngOnDestroy(): void;
504
636
  static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormComponent, never>;
505
637
  static ɵcmp: i0.ɵɵComponentDeclaration<NgsFormComponent, "ngs-form", never, {}, {}, never, never, true, never>;
506
638
  }
@@ -511,8 +643,18 @@ declare const NGS_FORMS_ITEM_DATA: InjectionToken<unknown>;
511
643
  * @internal
512
644
  */
513
645
  declare const NGS_FORMS_CONTROL_ADD_REMOVE_FN: InjectionToken<unknown>;
514
- /** Injection token for the row index when a component is rendered inside a form array list. */
515
- declare const NGS_FORMS_ITEM_INDEX: InjectionToken<unknown>;
646
+ /**
647
+ * Injection token for the row index when a component is rendered inside a form array list.
648
+ *
649
+ * @remarks This is the index the row had when the component was created. Rows before it can be removed later,
650
+ * so to find a row's current position use `NGS_FORMS_ARRAY_ROW` with `formArray.controls.indexOf(row)`.
651
+ */
652
+ declare const NGS_FORMS_ITEM_INDEX: InjectionToken<number>;
653
+ /**
654
+ * Injection token for the `UntypedFormGroup` of the form array row a component is rendered in. Unlike
655
+ * `NGS_FORMS_ITEM_INDEX`, it stays correct when earlier rows are removed.
656
+ */
657
+ declare const NGS_FORMS_ARRAY_ROW: InjectionToken<UntypedFormGroup>;
516
658
  type FormControlAddRemoveFn = (control: AbstractControl, controlName: string) => void;
517
659
  /**
518
660
  * @internal
@@ -576,12 +718,20 @@ declare class NgsFormItemController extends NgsSubscriber {
576
718
  private readonly addRemoveControlFn?;
577
719
  private readonly index?;
578
720
  private readonly changeDetectorRef?;
721
+ private readonly arrayRow?;
579
722
  private componentRef;
580
- private parentVisibility;
581
723
  private lastVisible;
582
- constructor(injector: Injector, viewContainerRef: ViewContainerRef, itemData: NgsFormsFormItem<any>, addRemoveControlFn?: INgsFormsFormControlAddRemove | undefined, index?: number | undefined, changeDetectorRef?: ChangeDetectorRef | undefined);
724
+ /** Incremented whenever a scheduled create becomes stale (hidden again, or destroyed). */
725
+ private createToken;
726
+ private destroyed;
727
+ constructor(injector: Injector, viewContainerRef: ViewContainerRef, itemData: NgsFormsFormItem<any>, addRemoveControlFn?: INgsFormsFormControlAddRemove | undefined, index?: number | undefined, changeDetectorRef?: ChangeDetectorRef | undefined, arrayRow?: UntypedFormGroup | undefined);
583
728
  destroy(): void;
584
729
  private bindVisibility;
730
+ /**
731
+ * Creates the component in a microtask. A create that is overtaken by a later visibility change or by
732
+ * `destroy()` before it runs is dropped.
733
+ */
734
+ private scheduleCreate;
585
735
  private create;
586
736
  private detach;
587
737
  }
@@ -592,7 +742,7 @@ declare class NgsFormItemController extends NgsSubscriber {
592
742
  * @remarks Use it inside custom container components to render child items:
593
743
  * `<ng-container [ngs-form-item]="item" [ngs-form-group]="group"></ng-container>`.
594
744
  */
595
- declare class NgsFormsFormItemDirective implements OnInit, OnDestroy {
745
+ declare class NgsFormsFormItemDirective implements OnInit, OnChanges, OnDestroy {
596
746
  /** The item to render. */
597
747
  itemData: NgsFormsFormItem<any> | undefined;
598
748
  /** Form group that the item's control is added to. */
@@ -600,7 +750,8 @@ declare class NgsFormsFormItemDirective implements OnInit, OnDestroy {
600
750
  /** Form array that the item's control is added to. */
601
751
  formArray?: UntypedFormArray;
602
752
  /**
603
- * Index of the item inside a form array row, provided to children as `NGS_FORMS_ITEM_INDEX`.
753
+ * Index of the item inside a form array row, provided to children as `NGS_FORMS_ITEM_INDEX`. When it is set, the
754
+ * `ngs-form-group` is also provided to children as `NGS_FORMS_ARRAY_ROW`.
604
755
  */
605
756
  index?: number;
606
757
  controller: NgsFormItemController | undefined;
@@ -608,7 +759,10 @@ declare class NgsFormsFormItemDirective implements OnInit, OnDestroy {
608
759
  private readonly injector;
609
760
  private readonly changeDetectorRef;
610
761
  private readonly formComponentRegistryService;
762
+ private initialized;
611
763
  ngOnInit(): void;
764
+ ngOnChanges(changes: SimpleChanges): void;
765
+ private build;
612
766
  ngOnDestroy(): void;
613
767
  static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormsFormItemDirective, never>;
614
768
  static ɵdir: i0.ɵɵDirectiveDeclaration<NgsFormsFormItemDirective, "[ngs-form-item]", never, { "itemData": { "alias": "ngs-form-item"; "required": false; }; "formGroup": { "alias": "ngs-form-group"; "required": false; }; "formArray": { "alias": "ngs-form-array"; "required": false; }; "index": { "alias": "ngs-form-index"; "required": false; }; }, {}, never, never, true, never>;
@@ -676,7 +830,7 @@ declare class NgsFormsRowComponent extends NgsFormsBaseClassFormComponent<NgsFor
676
830
  * })
677
831
  * ```
678
832
  */
679
- declare class NgsFormsFormGroupComponent extends NgsFormsFormItemWithVisibleAndValidatorsBase<NgsFormsFormGroupConfig> implements OnInit {
833
+ declare class NgsFormsFormGroupComponent extends NgsFormsFormItemWithVisibleAndValidatorsBase<NgsFormsFormGroupConfig, UntypedFormGroup> implements OnInit {
680
834
  static key: string;
681
835
  /** Creates a `form-group` item. */
682
836
  static create(config: NgsFormsFormGroupConfig): NgsFormsFormItem<NgsFormsFormGroupConfig>;
@@ -729,7 +883,7 @@ interface NgsFormItemArrayConfig extends NgsFormsFormItemConfigBaseItemWithNameA
729
883
  * @remarks Registry key: `form-array`. Put an `NgsFormsFormArrayListComponent` inside `items` to render the rows,
730
884
  * and `NgsFormsFormArrayAddItemComponent` / `NgsFormsFormArrayRemoveItemComponent` to let users change them.
731
885
  */
732
- declare class NgsFormsFormArrayContainerComponent extends NgsFormsFormItemWithVisibleAndValidatorsBase<NgsFormItemArrayConfig> {
886
+ declare class NgsFormsFormArrayContainerComponent extends NgsFormsFormItemWithVisibleAndValidatorsBase<NgsFormItemArrayConfig, UntypedFormArray> {
733
887
  private formArrayService;
734
888
  static key: string;
735
889
  constructor(formArrayService: NgsFormsFormArrayInternalService);
@@ -747,8 +901,11 @@ declare class NgsFormsFormArrayContainerComponent extends NgsFormsFormItemWithVi
747
901
  declare class NgsFormsFormArrayInternalService implements OnDestroy {
748
902
  config: NgsFormItemArrayConfig;
749
903
  readonly formArray: UntypedFormArray;
904
+ private readonly formsInternalService;
750
905
  /** Emits after a row is added or removed. */
751
906
  readonly itemsChanged: Subject<void>;
907
+ /** Emits the index of a row right after it is removed. */
908
+ readonly rowRemoved: Subject<number>;
752
909
  constructor();
753
910
  ngOnDestroy(): void;
754
911
  /** Removes the row at `index`, unless that would go below `minItems`. */
@@ -793,7 +950,14 @@ declare class NgsFormsFormArrayListComponent extends NgsFormsBaseClassFormCompon
793
950
  internalArrayService: NgsFormsFormArrayInternalService;
794
951
  myFormArray: FormArray<any>;
795
952
  private changeDetectorRef;
953
+ private elementRef;
954
+ private injector;
796
955
  ngOnInit(): void;
956
+ /**
957
+ * When the focused element (usually the row's Remove button) was removed with its row, moves focus to the
958
+ * same kind of control in the row that took its place, so keyboard users are not sent back to the top of the page.
959
+ */
960
+ private restoreFocusAfterRemove;
797
961
  /** Creates a `form-array-list` item. */
798
962
  static create(config: NgsFormsFormArrayListConfig): NgsFormsFormItem<NgsFormsFormArrayListConfig>;
799
963
  castToFormGroup(control: AbstractControl): UntypedFormGroup;
@@ -815,6 +979,12 @@ interface NgsFormItemArrayRemoveItemConfig extends NgsFormsFormItemConfigBase {
815
979
  buttonClass?: string;
816
980
  /** Class of an `<i>` icon shown before the label, for example `bi bi-trash`. */
817
981
  buttonIcon?: string;
982
+ /**
983
+ * Accessible name of the button, so screen reader users can tell the rows' buttons apart. A function receives
984
+ * the row's zero-based index.
985
+ * @defaultValue `${buttonText} item ${index + 1}`, for example `Remove item 2`
986
+ */
987
+ ariaLabel?: string | ((index: number) => string);
818
988
  }
819
989
 
820
990
  /**
@@ -823,14 +993,19 @@ interface NgsFormItemArrayRemoveItemConfig extends NgsFormsFormItemConfigBase {
823
993
  * @remarks Registry key: `form-array-remove-item`. Place it inside the `templateItem` of an
824
994
  * `NgsFormsFormArrayListComponent` so each row gets one.
825
995
  */
826
- declare class NgsFormsFormArrayRemoveItemComponent extends NgsFormsBaseClassFormComponent<NgsFormItemArrayRemoveItemConfig> {
996
+ declare class NgsFormsFormArrayRemoveItemComponent extends NgsFormsBaseClassFormComponent<NgsFormItemArrayRemoveItemConfig> implements OnInit {
827
997
  static key: string;
828
998
  internalArrayService: NgsFormsFormArrayInternalService;
829
999
  private elementRef;
830
1000
  private indexFromDi;
831
- /** Index of the row this button belongs to. */
1001
+ private row;
1002
+ private changeDetectorRef;
1003
+ /** Accessible name of the button, from `ariaLabel` or `${buttonText} item ${index + 1}`. */
1004
+ get ariaLabel(): string;
1005
+ /** Current index of the row this button belongs to. */
832
1006
  get myIndex(): number;
833
1007
  constructor();
1008
+ ngOnInit(): void;
834
1009
  /** Creates a `form-array-remove-item` item. */
835
1010
  static create(config: NgsFormItemArrayRemoveItemConfig): NgsFormsFormItem<NgsFormItemArrayRemoveItemConfig>;
836
1011
  removeItem(): void;
@@ -885,22 +1060,43 @@ declare class NgsFormsHtmlContentComponent extends NgsFormsBaseClassFormComponen
885
1060
  static ɵcmp: i0.ɵɵComponentDeclaration<NgsFormsHtmlContentComponent, "ngs-form-component-html-content", never, {}, {}, never, never, true, never>;
886
1061
  }
887
1062
 
1063
+ /** Configuration for `NgsFormsFormSectionComponent`. */
888
1064
  interface NgsFormsFormSectionConfig extends NgsFormsFormItemContainerConfigBase {
1065
+ /** Section heading. It also names the section's group for assistive technology. */
889
1066
  title: string;
1067
+ /**
1068
+ * Class of the title.
1069
+ * @defaultValue 'h3'
1070
+ */
890
1071
  titleClass?: string;
1072
+ /**
1073
+ * Heading level (1 to 6) that assistive technology announces for the title.
1074
+ * @defaultValue 3
1075
+ */
1076
+ headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
1077
+ /** Text shown under the title. */
891
1078
  subtitle?: string;
1079
+ /**
1080
+ * Class of the subtitle.
1081
+ * @defaultValue 'lead'
1082
+ */
892
1083
  subtitleClass?: string;
893
1084
  }
1085
+ /** @internal */
1086
+ declare const sectionConfigDefaults: Partial<NgsFormsFormSectionConfig>;
894
1087
 
895
1088
  /**
896
1089
  * Groups items under a title and optional subtitle. Does not create a form control, so child values stay in the
897
1090
  * parent group.
898
1091
  *
899
1092
  * @remarks Registry key: `section`. Config: `title`, `subtitle`, `titleClass` (default `h3`),
900
- * `subtitleClass` (default `lead`) and `items`.
1093
+ * `headingLevel` (default 3), `subtitleClass` (default `lead`) and `items`. The section is exposed to assistive
1094
+ * technology as a group named by its title.
901
1095
  */
902
1096
  declare class NgsFormsFormSectionComponent extends NgsFormsBaseClassItemsContainerBase<NgsFormsFormSectionConfig> implements OnInit {
903
1097
  static key: string;
1098
+ /** Element id of the title, used to name the section's group. */
1099
+ readonly titleId: string;
904
1100
  /** Creates a `section` item. */
905
1101
  static create(config: NgsFormsFormSectionConfig): NgsFormsFormItem<NgsFormsFormSectionConfig>;
906
1102
  ngOnInit(): void;
@@ -922,5 +1118,5 @@ declare class NgsFormsCoreModule {
922
1118
  static ɵinj: i0.ɵɵInjectorDeclaration<NgsFormsCoreModule>;
923
1119
  }
924
1120
 
925
- export { NGS_FORMS_CONTROL_ADD_REMOVE_FN, NGS_FORMS_ITEM_DATA, NGS_FORMS_ITEM_INDEX, NgsFormComponent, NgsFormsBaseClassFormComponent, NgsFormsBaseClassFormInputComponent, NgsFormsBaseClassFormItemInputWithOptionsComponent, NgsFormsBaseClassItemsContainerBase, NgsFormsColumnComponent, NgsFormsComponentRegistryService, NgsFormsCoreModule, NgsFormsFormArrayAddItemComponent, NgsFormsFormArrayContainerComponent, NgsFormsFormArrayInternalService, NgsFormsFormArrayListComponent, NgsFormsFormArrayRemoveItemComponent, NgsFormsFormControlAddRemoveFunctions, NgsFormsFormGroupComponent, NgsFormsFormItemDirective, NgsFormsFormItemWithVisibleAndValidatorsBase, NgsFormsFormSectionComponent, NgsFormsHtmlContentComponent, NgsFormsInternalService, NgsFormsRowComponent, NgsFormsService, NgsFormsTextDivComponent, NgsSubscriber, ngsDefaults };
926
- export type { INgsFormsFormControlAddRemove, NgsFormDisableFn, NgsFormItemArrayAddItemConfig, NgsFormItemArrayConfig, NgsFormItemArrayRemoveItemConfig, NgsFormItemHtmlContentConfig, NgsFormItemRowConfig, NgsFormItemVisibilityFn, NgsFormValidatorArrayBuilderFn, NgsFormsFormArrayListConfig, NgsFormsFormConfig, NgsFormsFormErrorKeyValueMap, NgsFormsFormGroupConfig, NgsFormsFormInputOption, NgsFormsFormItem, NgsFormsFormItemConfigBase, NgsFormsFormItemConfigBaseInput, NgsFormsFormItemConfigBaseInputWithOptions, NgsFormsFormItemConfigBaseItemWithNameAndValidators, NgsFormsFormItemConfigBaseTextInput, NgsFormsFormItemContainerConfigBase, NgsFormsFunctionParameters, NgsServerSideValidationErrorObjectType };
1121
+ export { NGS_FORMS_ARRAY_ROW, NGS_FORMS_CONTROL_ADD_REMOVE_FN, NGS_FORMS_ITEM_DATA, NGS_FORMS_ITEM_INDEX, NGS_FORMS_SERVER_ERROR, NgsFormComponent, NgsFormsBaseClassFormComponent, NgsFormsBaseClassFormInputComponent, NgsFormsBaseClassFormItemInputWithOptionsComponent, NgsFormsBaseClassItemsContainerBase, NgsFormsColumnComponent, NgsFormsComponentRegistryService, NgsFormsCoreModule, NgsFormsFormArrayAddItemComponent, NgsFormsFormArrayContainerComponent, NgsFormsFormArrayInternalService, NgsFormsFormArrayListComponent, NgsFormsFormArrayRemoveItemComponent, NgsFormsFormControlAddRemoveFunctions, NgsFormsFormGroupComponent, NgsFormsFormItemDirective, NgsFormsFormItemWithVisibleAndValidatorsBase, NgsFormsFormSectionComponent, NgsFormsHtmlContentComponent, NgsFormsInternalService, NgsFormsRowComponent, NgsFormsServerErrorRegistry, NgsFormsService, NgsFormsTextDivComponent, NgsSubscriber, constructServerErrorMessageObject, ngsDefaults, sectionConfigDefaults };
1122
+ export type { INgsFormsFormControlAddRemove, NgsFormDisableFn, NgsFormItemArrayAddItemConfig, NgsFormItemArrayConfig, NgsFormItemArrayRemoveItemConfig, NgsFormItemHtmlContentConfig, NgsFormItemRowConfig, NgsFormItemVisibilityFn, NgsFormValidatorArrayBuilderFn, NgsFormsCommonComponentState, NgsFormsFormArrayListConfig, NgsFormsFormConfig, NgsFormsFormErrorKeyValueMap, NgsFormsFormGroupConfig, NgsFormsFormInputOption, NgsFormsFormItem, NgsFormsFormItemConfigBase, NgsFormsFormItemConfigBaseInput, NgsFormsFormItemConfigBaseInputWithOptions, NgsFormsFormItemConfigBaseItemWithNameAndValidators, NgsFormsFormItemConfigBaseTextInput, NgsFormsFormItemContainerConfigBase, NgsFormsFormSectionConfig, NgsFormsFunctionParameters, NgsFormsGlobalFormState, NgsFormsServerErrorArray, NgsFormsServerErrorGroup, NgsFormsServerErrorPath, NgsFormsServerErrors, NgsFormsTextDivConfig, NgsServerSideValidationErrorObjectType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-simplicity/forms-core",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",