@ng-simplicity/forms-core 1.1.4 → 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
@@ -343,6 +343,84 @@ declare class NgsFormsComponentRegistryService {
343
343
  static ɵprov: i0.ɵɵInjectableDeclaration<NgsFormsComponentRegistryService>;
344
344
  }
345
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
+
346
424
  /**
347
425
  * Per form state holder that connects `<ngs-form>`, its items and `NgsFormsService`.
348
426
  *
@@ -356,6 +434,8 @@ declare class NgsFormsInternalService {
356
434
  state: BehaviorSubject<{
357
435
  [key: string]: any;
358
436
  }>;
437
+ /** Server errors set with `NgsFormsService.setServerErrorMessages()`. */
438
+ readonly serverErrors: NgsFormsServerErrorRegistry;
359
439
  setIsSubmitted(isSubmitted: boolean): void;
360
440
  /** `true` when no rendered control fails its validators. A form whose controls are all disabled counts as valid. */
361
441
  checkIsValid(): boolean;
@@ -407,6 +487,14 @@ declare class NgsFormsService implements OnDestroy {
407
487
  private lastConfig;
408
488
  private missingFormTimer;
409
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;
410
498
  /** `true` once the user has changed any control in the form. */
411
499
  get dirty(): boolean;
412
500
  /** `true` when every rendered control passes its validators. Hidden items are not validated. */
@@ -445,13 +533,44 @@ declare class NgsFormsService implements OnDestroy {
445
533
  /** Merges `state` into the state shared by every component in the form. */
446
534
  updateGlobalState(state: Partial<NgsFormsGlobalFormState>): void;
447
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;
448
553
  /**
449
554
  * Patches values into the form, using the same shape as `formValue$` (including the root group name).
450
555
  *
451
- * @remarks Only controls that are currently rendered receive values. Patch again after a conditional item becomes
452
- * 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.
453
562
  */
454
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;
455
574
  static ɵfac: i0.ɵɵFactoryDeclaration<NgsFormsService, never>;
456
575
  static ɵprov: i0.ɵɵInjectableDeclaration<NgsFormsService>;
457
576
  }
@@ -782,6 +901,7 @@ declare class NgsFormsFormArrayContainerComponent extends NgsFormsFormItemWithVi
782
901
  declare class NgsFormsFormArrayInternalService implements OnDestroy {
783
902
  config: NgsFormItemArrayConfig;
784
903
  readonly formArray: UntypedFormArray;
904
+ private readonly formsInternalService;
785
905
  /** Emits after a row is added or removed. */
786
906
  readonly itemsChanged: Subject<void>;
787
907
  /** Emits the index of a row right after it is removed. */
@@ -998,5 +1118,5 @@ declare class NgsFormsCoreModule {
998
1118
  static ɵinj: i0.ɵɵInjectorDeclaration<NgsFormsCoreModule>;
999
1119
  }
1000
1120
 
1001
- export { NGS_FORMS_ARRAY_ROW, 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, sectionConfigDefaults };
1002
- 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, NgsFormsTextDivConfig, 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.4",
3
+ "version": "1.1.5",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",