ngx-vest-forms 2.5.1 → 2.7.0

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/README.md CHANGED
@@ -124,6 +124,7 @@ That's all you need. The directive automatically creates controls, wires validat
124
124
  - `FormErrorDisplayDirective` (state + display policy)
125
125
  - `FormErrorControlDirective` (adds ARIA wiring + stable region IDs)
126
126
  - **Cross-field dependencies** — `validationConfig` for field-to-field triggers, `ROOT_FORM` for form-level rules
127
+ - **Field blur events** — `fieldBlur` output for blur-driven draft auto-save, analytics, and field-level side effects
127
128
  - **Utilities** — Field paths, field clearing, validation config builder
128
129
 
129
130
  ### Compatibility & Safety Notes (v2.x)
@@ -277,8 +278,99 @@ protected readonly validationConfig = {
277
278
 
278
279
  **Important**: `validationConfig` only triggers re-validation—validation logic is always defined in your Vest suite.
279
280
 
281
+ For dependent fields that should become invalid immediately but stay visually quiet until the
282
+ target field's own blur/display policy allows errors, combine `validationConfig` with
283
+ `errorDisplayMode="on-blur"` on the target wrappers:
284
+
285
+ ```typescript
286
+ protected readonly validationConfig = createValidationConfig<FormModel>()
287
+ .bidirectional('quantity', 'justification')
288
+ .build();
289
+ ```
290
+
291
+ This pairs well with `<ngx-control-wrapper [errorDisplayMode]="'on-blur'">`.
292
+
293
+ Avoid calling `triggerFormValidation()` from field-level blur handlers to force this UX.
294
+ `validationConfig` already re-runs the dependent validation, and the wrapper's
295
+ `errorDisplayMode` decides when the dependent field becomes visibly noisy.
296
+ Extra blur-triggered validation can restart async validators unnecessarily and make
297
+ the flow harder to reason about.
298
+
299
+ If you also want draft auto-save on blur, keep persistence separate from validation and
300
+ listen to the form's `fieldBlur` output. That gives you immediate dependent validity,
301
+ quiet untouched dependents, and blur-triggered save orchestration without coupling the
302
+ library to persistence policy.
303
+
280
304
  📖 **[Complete Guide: ValidationConfig vs Root-Form](./docs/VALIDATION-CONFIG-VS-ROOT-FORM.md)**
281
305
 
306
+ ### Field Blur Events & Draft Auto-Save
307
+
308
+ Use the form's `fieldBlur` output to build blur-driven workflows such as draft auto-save.
309
+
310
+ ```typescript
311
+ protected handleFieldBlur(event: NgxFieldBlurEvent<FormModel>): void {
312
+ if (!event.formValue || !event.dirty) {
313
+ return;
314
+ }
315
+
316
+ this.saveDraft(event.formValue);
317
+ }
318
+ ```
319
+
320
+ ```html
321
+ <form
322
+ ngxVestForm
323
+ [formValue]="formValue()"
324
+ (formValueChange)="formValue.set($event)"
325
+ (fieldBlur)="handleFieldBlur($event)"
326
+ >
327
+ <ngx-control-wrapper>
328
+ <label for="projectName">Project name</label>
329
+ <input id="projectName" name="projectName" [ngModel]="formValue().projectName" />
330
+ </ngx-control-wrapper>
331
+ </form>
332
+ ```
333
+
334
+ The output payload includes:
335
+
336
+ - `field`
337
+ - `value`
338
+ - `formValue`
339
+ - `dirty`
340
+ - `touched`
341
+ - `valid`
342
+ - `pending`
343
+
344
+ For draft persistence, prefer treating `pending` as informational metadata rather
345
+ than a blocker. If you gate blur saves on `pending`, async validation can prevent
346
+ the latest draft from being persisted even though the user has finished editing.
347
+
348
+ Both blur-save policies are supported:
349
+
350
+ - **Always save drafts** — recommended for draft persistence and recovery-oriented UX
351
+ - **Only save if valid** — useful when blur triggers stricter side effects instead of draft saves
352
+
353
+ For the valid-only variant, layer app policy on top of `fieldBlur`, for example:
354
+
355
+ ```typescript
356
+ protected handleFieldBlur(event: NgxFieldBlurEvent<FormModel>): void {
357
+ if (!event.formValue || !event.dirty || !event.valid || event.pending) {
358
+ return;
359
+ }
360
+
361
+ this.saveDraft(event.formValue);
362
+ }
363
+ ```
364
+
365
+ The examples app includes a complete blur-driven draft persistence implementation:
366
+
367
+ - route: `/auto-save-demo`
368
+ - source: `projects/examples/src/app/pages/auto-save-demo/`
369
+
370
+ That example intentionally demonstrates the **always-save draft** policy.
371
+
372
+ 📖 **[Guide: Auto-Save on Blur](./docs/AUTO-SAVE-ON-BLUR.md)**
373
+
282
374
  ### Root-Form Validation
283
375
 
284
376
  Form-level validation rules that don't belong to any specific field (e.g., "at least one contact method required").
@@ -401,6 +493,8 @@ const shape: NgxDeepRequired<MyFormModel> = {
401
493
  ### Advanced Patterns
402
494
 
403
495
  - **[ValidationConfig vs Root-Form](./docs/VALIDATION-CONFIG-VS-ROOT-FORM.md)** - Cross-field dependencies and form-level rules
496
+ - **[Auto-Save on Blur](./docs/AUTO-SAVE-ON-BLUR.md)** - Build draft persistence with `fieldBlur` and calm dependent validation
497
+ - **[Clear Submitted State](./docs/CLEAR-SUBMITTED-STATE.md)** - End a submit cycle without resetting values or control metadata
404
498
  - **[Field Path Types](./docs/FIELD-PATHS.md)** - Type-safe dot-notation paths for nested properties
405
499
  - **[Structure Change Detection](./docs/STRUCTURE_CHANGE_DETECTION.md)** - Handle dynamic form structure updates
406
500
  - **[Field Clearing Utilities](./docs/FIELD-CLEARING-UTILITIES.md)** - Type-safe utilities for clearing nested form values
@@ -408,6 +502,7 @@ const shape: NgxDeepRequired<MyFormModel> = {
408
502
  ### UI & Integration
409
503
 
410
504
  - **[Child Components](./docs/CHILD-COMPONENTS.md)** - Split large forms into smaller, maintainable components
505
+ - **[Composite Adapter Recipe](./docs/COMPOSITE-ADAPTER-RECIPE.md)** - Map one composite widget to multiple real form field paths
411
506
  - **[Custom Control Wrappers](./docs/CUSTOM-CONTROL-WRAPPERS.md)** - Build consistent error display patterns
412
507
  - **[API Tokens](./docs/API-TOKENS.md)** - Configure error display modes and other global settings
413
508
 
@@ -417,7 +512,7 @@ const shape: NgxDeepRequired<MyFormModel> = {
417
512
 
418
513
  ### Examples
419
514
 
420
- - **[Examples Project](./projects/examples)** - Working code examples with business hours forms, purchase forms, and validation config demos
515
+ - **[Examples Project](./projects/examples)** - Working code examples with business hours forms, purchase forms, validation config demos, and blur-driven draft auto-save
421
516
  - Run locally: `npm install && npm start`
422
517
  - Includes smart components, UI components, and complete validation patterns
423
518
 
@@ -470,6 +565,26 @@ This library was originally created by [Brecht Billiet](https://twitter.com/brec
470
565
 
471
566
  ## Developer Resources
472
567
 
568
+ ### Agent Skills
569
+
570
+ This repository ships an installable agent skill for ngx-vest-forms guidance.
571
+
572
+ Install it from the repository root with the `skills` CLI:
573
+
574
+ ```bash
575
+ npx skills add ngx-vest-forms/ngx-vest-forms --skill ngx-vest-forms
576
+ ```
577
+
578
+ This repository also ships an installable agent skill for **Vest.js 5.4 guidance**.
579
+
580
+ Install it from the repository root with the `skills` CLI:
581
+
582
+ ```bash
583
+ npx skills add ngx-vest-forms/ngx-vest-forms --skill vestjs
584
+ ```
585
+
586
+ See also: **[Vest.js 5.4 Agent Skill Guide](./docs/VESTJS-SKILL.md)**
587
+
473
588
  ### Comprehensive Instruction Files
474
589
 
475
590
  This project includes detailed instruction files designed to help developers master ngx-vest-forms and Vest.js patterns: