@firestitch/form 18.0.29 → 18.0.30

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.
Files changed (32) hide show
  1. package/app/components/form-dialog-actions/form-dialog-actions.component.d.ts +14 -2
  2. package/app/directives/button.directive.d.ts +1 -1
  3. package/app/directives/form/form.directive.d.ts +87 -29
  4. package/app/directives/form-base/form-base.directive.d.ts +73 -5
  5. package/app/directives/form-container/form-container.directive.d.ts +80 -0
  6. package/app/directives/form-container/index.d.ts +1 -0
  7. package/app/directives/index.d.ts +1 -1
  8. package/app/fs-form.module.d.ts +2 -2
  9. package/app/interfaces/form-owner.d.ts +17 -0
  10. package/app/interfaces/index.d.ts +1 -0
  11. package/app/services/fsform.service.d.ts +5 -5
  12. package/esm2022/app/components/form-dialog-actions/form-dialog-actions.component.mjs +41 -17
  13. package/esm2022/app/directives/button.directive.mjs +13 -8
  14. package/esm2022/app/directives/form/form.directive.mjs +238 -241
  15. package/esm2022/app/directives/form-base/form-base.directive.mjs +239 -6
  16. package/esm2022/app/directives/form-container/form-container.directive.mjs +164 -0
  17. package/esm2022/app/directives/form-container/index.mjs +2 -0
  18. package/esm2022/app/directives/index.mjs +2 -2
  19. package/esm2022/app/fs-form.module.mjs +6 -6
  20. package/esm2022/app/guards/form-deactivate.guard.mjs +1 -1
  21. package/esm2022/app/interfaces/form-owner.mjs +2 -0
  22. package/esm2022/app/interfaces/index.mjs +2 -1
  23. package/esm2022/app/services/fsform.service.mjs +10 -7
  24. package/esm2022/public_api.mjs +2 -2
  25. package/fesm2022/firestitch-form.mjs +702 -317
  26. package/fesm2022/firestitch-form.mjs.map +1 -1
  27. package/package.json +1 -1
  28. package/public_api.d.ts +2 -1
  29. package/app/directives/form-group/form-group.directive.d.ts +0 -15
  30. package/app/directives/form-group/index.d.ts +0 -1
  31. package/esm2022/app/directives/form-group/form-group.directive.mjs +0 -35
  32. package/esm2022/app/directives/form-group/index.mjs +0 -2
@@ -1,16 +1,28 @@
1
1
  import { OnDestroy, OnInit } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  export declare class FsFormDialogActionsComponent implements OnInit, OnDestroy {
4
- private _form;
5
- private _cdRef;
4
+ /** Leave unset inside an `fsFormContainer` to follow whether it has anything to save. */
6
5
  save: boolean;
7
6
  create: boolean;
8
7
  close: boolean;
8
+ /** Leave unset inside an `fsFormContainer` to fill in whenever Save does not apply. */
9
9
  done: boolean;
10
10
  closeData: any;
11
11
  name: string;
12
12
  dirty: boolean;
13
13
  private _destroy$;
14
+ private _container;
15
+ private _form;
16
+ private _cdRef;
17
+ /**
18
+ * Inside a container these default to whether anything mounted can actually
19
+ * save, so a footer left as a bare `<fs-form-dialog-actions>` swaps Save for
20
+ * Done as tabs change without the dialog listing which tabs are savable. An
21
+ * explicit binding always wins, and outside a container Save stays on as it
22
+ * always did.
23
+ */
24
+ get showSave(): boolean;
25
+ get showDone(): boolean;
14
26
  ngOnInit(): void;
15
27
  ngOnDestroy(): void;
16
28
  static ɵfac: i0.ɵɵFactoryDeclaration<FsFormDialogActionsComponent, never>;
@@ -11,7 +11,7 @@ export declare class FsButtonDirective implements OnInit, OnDestroy {
11
11
  private _formDisabled;
12
12
  private _previousDisabled;
13
13
  private _destroy$;
14
- private _formGroup;
14
+ private _container;
15
15
  private _form;
16
16
  private _matButton;
17
17
  private _elementRef;
@@ -3,34 +3,37 @@ import { NgForm } from '@angular/forms';
3
3
  import { Observable } from 'rxjs';
4
4
  import { FsFormBaseDirective } from '../form-base';
5
5
  import { ConfirmResult } from './../../enums/confirm-result';
6
- import { ConfirmConfig, SubmittedEvent } from './../../interfaces';
6
+ import { FormStatus } from './../../enums/form-status';
7
+ import { SubmittedEvent } from './../../interfaces';
7
8
  import { SubmitEvent } from './../../interfaces/submit-event';
8
9
  import * as i0 from "@angular/core";
9
10
  export declare class FsFormDirective extends FsFormBaseDirective implements OnInit, OnDestroy, AfterContentInit, OnChanges {
10
11
  ngForm: NgForm;
11
- private _form;
12
- private _element;
13
- private _message;
14
- private _formGroup;
15
- private _dialogRef;
16
- private _drawerRef;
17
- private _route;
18
12
  wrapperSelector: string;
19
13
  messageSelector: string;
20
14
  hintSelector: string;
21
15
  labelSelector: string;
22
16
  autocomplete: boolean;
23
- shortcuts: boolean;
24
- confirm: ConfirmConfig | boolean;
25
- confirmDialog: boolean;
26
- confirmDrawer: boolean;
27
- confirmBrowser: boolean;
28
17
  dirtySubmitButton: boolean;
29
18
  set submit(submit$: (event: SubmitEvent) => Observable<any>);
30
19
  get submit(): (event: SubmitEvent) => Observable<any>;
31
20
  successDelay: number;
32
21
  errorDelay: number;
33
- deactivationGuard: boolean;
22
+ /**
23
+ * Whether this form joins the set around it - the `fsForm` it is nested inside,
24
+ * or the `fsFormContainer` enclosing it.
25
+ *
26
+ * Forms in a set behave as one submittable unit: the outermost form is what the
27
+ * submit buttons drive, and validation, dirty state, the unsaved-changes
28
+ * confirm and the pristine reset all span the set. That is what lets a form
29
+ * wrap only one tab's fields while the dialog footer stays outside it.
30
+ *
31
+ * Set `[link]="false"` for a panel that owns its own saving - an instant-save
32
+ * side panel, say. It keeps every fsForm feature for itself, but its dirty
33
+ * state never enables the outer Save button, its validation never blocks the
34
+ * outer submit, and the outer submit never touches it.
35
+ */
36
+ link: boolean;
34
37
  submitEvent: EventEmitter<SubmitEvent>;
35
38
  invalid: EventEmitter<SubmitEvent>;
36
39
  valid: EventEmitter<SubmitEvent>;
@@ -39,19 +42,73 @@ export declare class FsFormDirective extends FsFormBaseDirective implements OnIn
39
42
  cleared: EventEmitter<SubmitEvent>;
40
43
  fsFormClass: boolean;
41
44
  private _registerControl;
42
- private _dialogBackdropEscape;
43
45
  private _snapshot;
44
- private _activatedRouteConfig;
45
46
  private _status$;
46
47
  private _submit$;
48
+ private _linkedForms;
49
+ private _containerParent;
50
+ private _dirtyChange$;
51
+ private _message;
52
+ private _container;
53
+ private _ancestorForm;
54
+ /**
55
+ * Emits whenever the set's dirty state may have moved. Anything outside the
56
+ * form that renders off it - the dialog actions, say - can't watch
57
+ * `ngForm.valueChanges` on its own, because the edits happen in a nested form's
58
+ * NgForm, not this one's.
59
+ */
60
+ get dirtyChange$(): Observable<void>;
61
+ get submitted$(): Observable<SubmittedEvent>;
62
+ get status$(): Observable<FormStatus>;
63
+ get element(): HTMLElement;
64
+ /** True when a Save button driving this form would have something to run. */
65
+ get hasSubmit(): boolean;
66
+ /**
67
+ * The form this one is linked into, or null when it is a root - either because
68
+ * nothing encloses it or because `[link]="false"` cut it loose. A container
69
+ * supplies the parent when the forms are siblings rather than nested.
70
+ */
71
+ get parentForm(): FsFormDirective;
72
+ /** The outermost form of this set. Submit buttons drive this one. */
73
+ get rootForm(): FsFormDirective;
74
+ /** This form plus every form linked into it, at any depth. */
75
+ get linkedForms(): FsFormDirective[];
76
+ /** True when this form or anything linked into it has unsaved changes. */
77
+ get dirtyLinked(): boolean;
78
+ /**
79
+ * True when this form or anything linked into it has a submit handler - i.e.
80
+ * there is something for a Save button to do. A dialog footer can bind to this
81
+ * to swap Save for Done as the mounted tab changes, instead of hard-coding
82
+ * which tab names happen to be savable.
83
+ */
84
+ get submits(): boolean;
47
85
  get submitting(): boolean;
48
86
  get validating(): boolean;
49
87
  get completing(): boolean;
88
+ /**
89
+ * True when nothing above this form speaks for the set it belongs to. Reads the
90
+ * raw injections rather than `parentForm`, so an unlinked panel inside a dialog
91
+ * still defers to whatever encloses it instead of registering a second backdrop
92
+ * confirm on the same dialog.
93
+ */
94
+ private get _owns();
50
95
  private get _submitEvent();
51
96
  private get _formValidState$();
52
97
  private get _formInvalidState$();
53
98
  private get _submitter();
54
99
  ngOnInit(): void;
100
+ /**
101
+ * Take a nested form into this one's set. Called by the child on init, or by a
102
+ * container linking its siblings - consumers never call it directly.
103
+ */
104
+ linkForm(form: FsFormDirective): void;
105
+ unlinkForm(form: FsFormDirective): void;
106
+ /**
107
+ * Adopt a parent that DI could not supply. Only a container calls this, to link
108
+ * forms that are siblings in the template into one set.
109
+ */
110
+ linkTo(form: FsFormDirective): void;
111
+ unlinkFrom(): void;
55
112
  ngOnChanges(changes: SimpleChanges): void;
56
113
  clearSubmit(submit?: (event: SubmitEvent) => Observable<any>): void;
57
114
  registerSubmit(submit$: () => Observable<any>): void;
@@ -72,22 +129,25 @@ export declare class FsFormDirective extends FsFormBaseDirective implements OnIn
72
129
  enable(): void;
73
130
  disable(): void;
74
131
  validate(): void;
75
- submit$(submitEvent: SubmitEvent): Observable<SubmittedEvent>;
132
+ submit$(submitEvent?: SubmitEvent): Observable<SubmittedEvent>;
76
133
  private _listenSubmit;
77
134
  private _listenFormStatus;
78
- private _listenWindowClose;
79
- private _activeDialog;
80
- private _listenHotKeys;
81
- private _formClose;
82
135
  private _getActiveSubmitButton;
83
- private _elementInForm;
84
136
  private _completeSubmit;
85
- private _getFormGroup;
137
+ /**
138
+ * Whoever holds the submit buttons for this form. A container when one encloses
139
+ * it, otherwise the root of its linked set - the button that saves a tab's form
140
+ * typically sits outside it, down in the dialog footer.
141
+ *
142
+ * Only a form that actually joined the container may drive its buttons. DI
143
+ * hands `_container` to every form inside, including one cut loose with
144
+ * `[link]="false"`, and an instant-save panel is usually `[confirm]="false"`
145
+ * too - so without this it would take the `!confirm` branch below and
146
+ * re-enable the footer's Save button that the linked set had just disabled.
147
+ */
148
+ private _getOwner;
86
149
  private _resetButtons;
87
150
  private _registerConfirm;
88
- private _registerDrawerClose;
89
- private _registerConfirmDrawerClose;
90
- private _registerConfirmDialogBackdropEscape;
91
151
  private _registerAutocomplete;
92
152
  private _registerDirtySubmitButton;
93
153
  private _updateDirtySubmitButtons;
@@ -97,8 +157,6 @@ export declare class FsFormDirective extends FsFormBaseDirective implements OnIn
97
157
  private _disableButtons;
98
158
  private _waitUntilStatusPending;
99
159
  private _handleError;
100
- private _registerCanDeactivateGuard;
101
- private _cleanupCanDeactivate;
102
160
  static ɵfac: i0.ɵɵFactoryDeclaration<FsFormDirective, never>;
103
- static ɵdir: i0.ɵɵDirectiveDeclaration<FsFormDirective, "[fsForm]", ["fsForm"], { "wrapperSelector": { "alias": "wrapperSelector"; "required": false; }; "messageSelector": { "alias": "messageSelector"; "required": false; }; "hintSelector": { "alias": "hintSelector"; "required": false; }; "labelSelector": { "alias": "labelSelector"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; "shortcuts": { "alias": "shortcuts"; "required": false; }; "confirm": { "alias": "confirm"; "required": false; }; "confirmDialog": { "alias": "confirmDialog"; "required": false; }; "confirmDrawer": { "alias": "confirmDrawer"; "required": false; }; "confirmBrowser": { "alias": "confirmBrowser"; "required": false; }; "dirtySubmitButton": { "alias": "dirtySubmitButton"; "required": false; }; "submit": { "alias": "submit"; "required": false; }; "successDelay": { "alias": "successDelay"; "required": false; }; "errorDelay": { "alias": "errorDelay"; "required": false; }; "deactivationGuard": { "alias": "deactivationGuard"; "required": false; }; }, { "submitEvent": "fsForm"; "invalid": "invalid"; "valid": "valid"; "submitted": "submitted"; "reseted": "reseted"; "cleared": "cleared"; }, never, never, true, never>;
161
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FsFormDirective, "[fsForm]", ["fsForm"], { "wrapperSelector": { "alias": "wrapperSelector"; "required": false; }; "messageSelector": { "alias": "messageSelector"; "required": false; }; "hintSelector": { "alias": "hintSelector"; "required": false; }; "labelSelector": { "alias": "labelSelector"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; "dirtySubmitButton": { "alias": "dirtySubmitButton"; "required": false; }; "submit": { "alias": "submit"; "required": false; }; "successDelay": { "alias": "successDelay"; "required": false; }; "errorDelay": { "alias": "errorDelay"; "required": false; }; "link": { "alias": "link"; "required": false; }; }, { "submitEvent": "fsForm"; "invalid": "invalid"; "valid": "valid"; "submitted": "submitted"; "reseted": "reseted"; "cleared": "cleared"; }, never, never, true, never>;
104
162
  }
@@ -1,21 +1,62 @@
1
- import { AfterContentInit, ChangeDetectorRef, NgZone, OnDestroy, QueryList } from '@angular/core';
1
+ import { AfterContentInit, ChangeDetectorRef, ElementRef, NgZone, OnDestroy, OnInit, QueryList } from '@angular/core';
2
+ import { ActivatedRoute, Route } from '@angular/router';
3
+ import { MatDialogRef } from '@angular/material/dialog';
2
4
  import { MatTabGroup } from '@angular/material/tabs';
5
+ import { DrawerRef } from '@firestitch/drawer';
3
6
  import { Observable } from 'rxjs';
4
7
  import { ConfirmResult } from '../../enums';
5
- import { ConfirmConfig } from '../../interfaces';
8
+ import { FormStatus } from '../../enums/form-status';
9
+ import { ConfirmConfig, SubmitEvent, SubmittedEvent } from '../../interfaces';
10
+ import { FsForm } from '../../services/fsform.service';
6
11
  import { FsButtonDirective } from '../button.directive';
12
+ import type { FsFormDirective } from '../form/form.directive';
7
13
  import * as i0 from "@angular/core";
8
- export declare abstract class FsFormBaseDirective implements AfterContentInit, OnDestroy {
14
+ /**
15
+ * Shared by the two things that can own a set of forms: an `fsForm` sitting at
16
+ * the root of its linked set, and an `fsFormContainer` holding forms that are
17
+ * siblings rather than nested.
18
+ *
19
+ * It holds the submit-button registry both of them expose to buttons, and the
20
+ * lifecycle that belongs to the set as a whole rather than to any one form -
21
+ * the dialog backdrop and Escape, Ctrl+S, the browser close prompt, the drawer
22
+ * and tab-switch confirms. Exactly one owner registers that lifecycle; see
23
+ * `_registerOwnerLifecycle`.
24
+ */
25
+ export declare abstract class FsFormBaseDirective implements OnInit, AfterContentInit, OnDestroy {
9
26
  confirmTabs: boolean;
10
27
  tabGroup: MatTabGroup;
28
+ confirm: ConfirmConfig | boolean;
29
+ confirmDialog: boolean;
30
+ confirmDrawer: boolean;
31
+ confirmBrowser: boolean;
32
+ shortcuts: boolean;
33
+ deactivationGuard: boolean;
11
34
  protected _ngZone: NgZone;
12
35
  protected _cdRef: ChangeDetectorRef;
36
+ protected _element: ElementRef<any>;
37
+ protected _form: FsForm;
38
+ protected _route: ActivatedRoute;
39
+ protected _dialogRef: MatDialogRef<any, any>;
40
+ protected _drawerRef: DrawerRef<any, any>;
41
+ protected _dialogBackdropEscape: boolean;
42
+ protected _activatedRouteConfig: Route | null;
13
43
  private _tabGroups;
14
44
  private _buttons;
15
45
  private _activeSubmitButton;
46
+ private _confirmTabGroups;
16
47
  private _destroy$;
17
48
  abstract submitting: boolean;
18
- abstract confirm: ConfirmConfig | boolean;
49
+ /** True when anything in the owned set has unsaved changes. */
50
+ abstract dirtyLinked: boolean;
51
+ /** Every form in the owned set, at any depth. */
52
+ abstract linkedForms: FsFormDirective[];
53
+ /** Emits whenever the owned set's dirty state may have moved. */
54
+ abstract dirtyChange$: Observable<void>;
55
+ /** Emits once a submit over the owned set has completed successfully. */
56
+ abstract submitted$: Observable<SubmittedEvent>;
57
+ /** Tracks the owned set's submit lifecycle, so the drawer can wait one out. */
58
+ abstract status$: Observable<FormStatus>;
59
+ ngOnInit(): void;
19
60
  ngAfterContentInit(): void;
20
61
  get destroy$(): Observable<void>;
21
62
  ngOnDestroy(): void;
@@ -24,11 +65,38 @@ export declare abstract class FsFormBaseDirective implements AfterContentInit, O
24
65
  set activeSubmitButton(button: FsButtonDirective);
25
66
  addButton(button: FsButtonDirective): void;
26
67
  removeButton(button: FsButtonDirective): void;
68
+ /**
69
+ * Everything here acts on the form set as a whole, so exactly one thing may
70
+ * register it. A form linked into a parent defers to that parent; every form
71
+ * inside a container defers to the container. Registering twice would put two
72
+ * confirms on the same backdrop click and two handlers on the same Ctrl+S.
73
+ */
74
+ protected _registerOwnerLifecycle(): void;
75
+ /** The half of the same ownership that needs projected content resolved. */
76
+ protected _registerOwnerContentLifecycle(): void;
77
+ /**
78
+ * Whether the element is inside what this owner covers. Overridden by the
79
+ * container, whose own element is a poor proxy: it may be an `<ng-container>`,
80
+ * which is a comment node and contains nothing.
81
+ */
82
+ protected _containsElement(el: Element): boolean;
83
+ protected _nodeContains(root: Node, el: Element): boolean;
84
+ protected _formClose(): void;
85
+ private _listenWindowClose;
86
+ private _activeDialog;
87
+ private _listenHotKeys;
88
+ private _registerConfirmDialogBackdropEscape;
89
+ private _registerDrawerClose;
90
+ private _registerConfirmDrawerClose;
27
91
  private _registerConfirmTabs;
28
92
  private _registerConfirmTabGroups;
29
93
  private _registerConfirmTabGroup;
94
+ private _registerCanDeactivateGuard;
95
+ private _cleanupCanDeactivate;
30
96
  abstract triggerSubmit(): void;
31
97
  abstract triggerConfirm(): Observable<ConfirmResult>;
98
+ abstract reset(): void;
99
+ abstract submit$(event?: SubmitEvent): Observable<SubmittedEvent>;
32
100
  static ɵfac: i0.ɵɵFactoryDeclaration<FsFormBaseDirective, never>;
33
- static ɵdir: i0.ɵɵDirectiveDeclaration<FsFormBaseDirective, never, never, { "confirmTabs": { "alias": "confirmTabs"; "required": false; }; "tabGroup": { "alias": "tabGroup"; "required": false; }; }, {}, ["_tabGroups"], never, false, never>;
101
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FsFormBaseDirective, never, never, { "confirmTabs": { "alias": "confirmTabs"; "required": false; }; "tabGroup": { "alias": "tabGroup"; "required": false; }; "confirm": { "alias": "confirm"; "required": false; }; "confirmDialog": { "alias": "confirmDialog"; "required": false; }; "confirmDrawer": { "alias": "confirmDrawer"; "required": false; }; "confirmBrowser": { "alias": "confirmBrowser"; "required": false; }; "shortcuts": { "alias": "shortcuts"; "required": false; }; "deactivationGuard": { "alias": "deactivationGuard"; "required": false; }; }, {}, ["_tabGroups"], never, false, never>;
34
102
  }
@@ -0,0 +1,80 @@
1
+ import { Observable } from 'rxjs';
2
+ import { ConfirmResult } from '../../enums';
3
+ import { FormStatus } from '../../enums/form-status';
4
+ import { FsFormOwner, SubmitEvent, SubmittedEvent } from '../../interfaces';
5
+ import { FsFormBaseDirective } from '../form-base';
6
+ import type { FsFormDirective } from '../form/form.directive';
7
+ import * as i0 from "@angular/core";
8
+ /**
9
+ * Bounds a set of forms without being one.
10
+ *
11
+ * An `fsForm` can only reach the forms nested inside it through DI, which forces
12
+ * a wrapper carrying `ngForm` around anything that needs to see them - and that
13
+ * wrapper then owns a real, empty `NgForm` whose control namespace every field
14
+ * below it falls into. A container has no `ngForm` and no controls. It only
15
+ * watches: forms register themselves as they mount, buttons resolve to it, and
16
+ * `fs-form-dialog-actions` reads Save-vs-Done off it. Put it on whatever element
17
+ * already frames the layout - or on an `<ng-container>` for no element at all.
18
+ *
19
+ * Forms in a container are siblings rather than nested, so on registration each
20
+ * one is linked into the first. That reproduces exactly the structure DI nesting
21
+ * builds, which is why validation, dirty state, the unsaved-changes confirm and
22
+ * the submit chain all span a container without any of that machinery knowing
23
+ * containers exist.
24
+ *
25
+ * A form marked `[link]="false"` never registers, so an instant-save panel stays
26
+ * out of the set the same way it does when nested.
27
+ */
28
+ export declare class FsFormContainerDirective extends FsFormBaseDirective implements FsFormOwner {
29
+ private _forms;
30
+ private _formsChange$;
31
+ /** The forms registered into this container, in registration order. */
32
+ get forms(): FsFormDirective[];
33
+ /**
34
+ * The form the rest of the set is linked into, or null while the container
35
+ * holds none - an open tab that has nothing to save, say.
36
+ */
37
+ get rootForm(): FsFormDirective;
38
+ /** Emits whenever a form registers or deregisters. */
39
+ get formsChange$(): Observable<void>;
40
+ get linkedForms(): FsFormDirective[];
41
+ /**
42
+ * True when anything in the container has a submit handler - i.e. there is
43
+ * something for a Save button to do. `fs-form-dialog-actions` reads this to
44
+ * swap Save for Done as the mounted tab changes, so a dialog never has to keep
45
+ * a list of which tabs happen to be savable.
46
+ */
47
+ get submits(): boolean;
48
+ get dirtyLinked(): boolean;
49
+ get submitting(): boolean;
50
+ /**
51
+ * Emits whenever the set's dirty state may have moved, including when the set
52
+ * itself changes. Anything rendering off it - the dialog actions - subscribes
53
+ * once and outlives any particular form, so this has to follow the root across
54
+ * tab switches rather than bind to whichever form happened to be first.
55
+ */
56
+ get dirtyChange$(): Observable<void>;
57
+ get submitted$(): Observable<SubmittedEvent>;
58
+ get status$(): Observable<FormStatus>;
59
+ /**
60
+ * Take a form into the container. Called by the form on init - consumers never
61
+ * call it directly.
62
+ */
63
+ registerForm(form: FsFormDirective): void;
64
+ /**
65
+ * Material attaches an incoming tab body before it detaches the outgoing one,
66
+ * so losing the root is a routine reshuffle rather than teardown. Re-elect and
67
+ * re-link the survivors instead of leaving them pointing at a dead root, and
68
+ * only let go of forms actually registered - clearing unconditionally would
69
+ * drop the form that just arrived.
70
+ */
71
+ deregisterForm(form?: FsFormDirective): void;
72
+ triggerSubmit(): void;
73
+ triggerConfirm(): Observable<ConfirmResult>;
74
+ submit$(event?: SubmitEvent): Observable<SubmittedEvent>;
75
+ reset(): void;
76
+ validate(): void;
77
+ protected _containsElement(el: Element): boolean;
78
+ static ɵfac: i0.ɵɵFactoryDeclaration<FsFormContainerDirective, never>;
79
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FsFormContainerDirective, "fs-form-container,[fsFormContainer]", ["fsFormContainer"], {}, {}, never, never, true, never>;
80
+ }
@@ -0,0 +1 @@
1
+ export * from './form-container.directive';
@@ -1,5 +1,5 @@
1
1
  export * from './form';
2
- export * from './form-group';
2
+ export * from './form-container';
3
3
  export * from './validators';
4
4
  export * from './button.directive';
5
5
  export * from './form-dialog-close.directive';
@@ -34,10 +34,10 @@ import * as i31 from "./directives/button.directive";
34
34
  import * as i32 from "./directives/submit-button.directive";
35
35
  import * as i33 from "./directives/form-template.directive";
36
36
  import * as i34 from "./directives/form-template-outlet.directive";
37
- import * as i35 from "./directives/form-group/form-group.directive";
37
+ import * as i35 from "./directives/form-container/form-container.directive";
38
38
  export declare class FsFormModule {
39
39
  static forRoot(): ModuleWithProviders<FsFormModule>;
40
40
  static ɵfac: i0.ɵɵFactoryDeclaration<FsFormModule, never>;
41
- static ɵmod: i0.ɵɵNgModuleDeclaration<FsFormModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i3.MatButtonModule, typeof i4.MatDialogModule, typeof i4.MatDialogModule, typeof i5.FsDialogModule, typeof i6.FsFormDirective, typeof i7.FsControlDirective, typeof i8.FsFormRequiredDirective, typeof i9.FsFormMinDirective, typeof i10.FsFormMaxDirective, typeof i11.FsFormMinLengthDirective, typeof i12.FsFormMaxLengthDirective, typeof i13.FsFormEmailDirective, typeof i14.FsFormEmailsDirective, typeof i15.FsFormPhoneDirective, typeof i16.FsFormCompareDirective, typeof i17.FsFormIntegerDirective, typeof i18.FsFormNumericDirective, typeof i19.FsFormPatternDirective, typeof i20.FsFormFunctionDirective, typeof i21.FsFormDateRangeDirective, typeof i22.FsFormGreaterDirective, typeof i23.FsFormGreaterEqualDirective, typeof i24.FsFormLesserDirective, typeof i25.FsFormLesserEqualDirective, typeof i26.FsFormUrlDirective, typeof i27.FsFormDialogCloseDirective, typeof i28.FsFormValidateDirective, typeof i29.FsFormDialogActionsComponent, typeof i30.FsFormNoFsValidatorsDirective, typeof i31.FsButtonDirective, typeof i32.FsSubmitButtonDirective, typeof i33.FsFormTemplateDirective, typeof i33.FsFormTemplateDirective, typeof i34.FsFormTemplateOutletDirective, typeof i35.FsFormGroupDirective], [typeof i6.FsFormDirective, typeof i7.FsControlDirective, typeof i8.FsFormRequiredDirective, typeof i9.FsFormMinDirective, typeof i10.FsFormMaxDirective, typeof i11.FsFormMinLengthDirective, typeof i12.FsFormMaxLengthDirective, typeof i13.FsFormEmailDirective, typeof i14.FsFormEmailsDirective, typeof i15.FsFormPhoneDirective, typeof i16.FsFormCompareDirective, typeof i17.FsFormIntegerDirective, typeof i18.FsFormNumericDirective, typeof i19.FsFormPatternDirective, typeof i20.FsFormFunctionDirective, typeof i21.FsFormDateRangeDirective, typeof i22.FsFormGreaterDirective, typeof i23.FsFormGreaterEqualDirective, typeof i24.FsFormLesserDirective, typeof i25.FsFormLesserEqualDirective, typeof i26.FsFormUrlDirective, typeof i27.FsFormDialogCloseDirective, typeof i28.FsFormValidateDirective, typeof i29.FsFormDialogActionsComponent, typeof i30.FsFormNoFsValidatorsDirective, typeof i31.FsButtonDirective, typeof i32.FsSubmitButtonDirective, typeof i33.FsFormTemplateDirective, typeof i33.FsFormTemplateDirective, typeof i34.FsFormTemplateOutletDirective, typeof i35.FsFormGroupDirective]>;
41
+ static ɵmod: i0.ɵɵNgModuleDeclaration<FsFormModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i3.MatButtonModule, typeof i4.MatDialogModule, typeof i4.MatDialogModule, typeof i5.FsDialogModule, typeof i6.FsFormDirective, typeof i7.FsControlDirective, typeof i8.FsFormRequiredDirective, typeof i9.FsFormMinDirective, typeof i10.FsFormMaxDirective, typeof i11.FsFormMinLengthDirective, typeof i12.FsFormMaxLengthDirective, typeof i13.FsFormEmailDirective, typeof i14.FsFormEmailsDirective, typeof i15.FsFormPhoneDirective, typeof i16.FsFormCompareDirective, typeof i17.FsFormIntegerDirective, typeof i18.FsFormNumericDirective, typeof i19.FsFormPatternDirective, typeof i20.FsFormFunctionDirective, typeof i21.FsFormDateRangeDirective, typeof i22.FsFormGreaterDirective, typeof i23.FsFormGreaterEqualDirective, typeof i24.FsFormLesserDirective, typeof i25.FsFormLesserEqualDirective, typeof i26.FsFormUrlDirective, typeof i27.FsFormDialogCloseDirective, typeof i28.FsFormValidateDirective, typeof i29.FsFormDialogActionsComponent, typeof i30.FsFormNoFsValidatorsDirective, typeof i31.FsButtonDirective, typeof i32.FsSubmitButtonDirective, typeof i33.FsFormTemplateDirective, typeof i33.FsFormTemplateDirective, typeof i34.FsFormTemplateOutletDirective, typeof i35.FsFormContainerDirective], [typeof i6.FsFormDirective, typeof i7.FsControlDirective, typeof i8.FsFormRequiredDirective, typeof i9.FsFormMinDirective, typeof i10.FsFormMaxDirective, typeof i11.FsFormMinLengthDirective, typeof i12.FsFormMaxLengthDirective, typeof i13.FsFormEmailDirective, typeof i14.FsFormEmailsDirective, typeof i15.FsFormPhoneDirective, typeof i16.FsFormCompareDirective, typeof i17.FsFormIntegerDirective, typeof i18.FsFormNumericDirective, typeof i19.FsFormPatternDirective, typeof i20.FsFormFunctionDirective, typeof i21.FsFormDateRangeDirective, typeof i22.FsFormGreaterDirective, typeof i23.FsFormGreaterEqualDirective, typeof i24.FsFormLesserDirective, typeof i25.FsFormLesserEqualDirective, typeof i26.FsFormUrlDirective, typeof i27.FsFormDialogCloseDirective, typeof i28.FsFormValidateDirective, typeof i29.FsFormDialogActionsComponent, typeof i30.FsFormNoFsValidatorsDirective, typeof i31.FsButtonDirective, typeof i32.FsSubmitButtonDirective, typeof i33.FsFormTemplateDirective, typeof i33.FsFormTemplateDirective, typeof i34.FsFormTemplateOutletDirective, typeof i35.FsFormContainerDirective]>;
42
42
  static ɵinj: i0.ɵɵInjectorDeclaration<FsFormModule>;
43
43
  }
@@ -0,0 +1,17 @@
1
+ import { Observable } from 'rxjs';
2
+ import type { FsFormDirective } from '../directives/form/form.directive';
3
+ import { ConfirmConfig } from './confirm-config';
4
+ import { SubmitEvent } from './submit-event';
5
+ import { SubmittedEvent } from './submitted-event';
6
+ /**
7
+ * What the unsaved-changes confirm and the route guard need from whatever owns a
8
+ * set of forms. Both an `fsForm` at the root of its linked set and an
9
+ * `fsFormContainer` holding several satisfy it, so neither caller has to know
10
+ * which of the two it was handed.
11
+ */
12
+ export interface FsFormOwner {
13
+ confirm: ConfirmConfig | boolean;
14
+ linkedForms: FsFormDirective[];
15
+ reset(): void;
16
+ submit$(event?: SubmitEvent): Observable<SubmittedEvent>;
17
+ }
@@ -2,3 +2,4 @@ export * from './submit-event';
2
2
  export * from './submitted-event';
3
3
  export * from './confirm-config';
4
4
  export * from './confirm-tab-group';
5
+ export * from './form-owner';
@@ -1,16 +1,16 @@
1
1
  import { Type } from '@angular/core';
2
2
  import { Observable } from 'rxjs';
3
- import type { FsFormDirective } from '../directives/form/form.directive';
4
3
  import { ConfirmResult } from '../enums';
4
+ import { FsFormOwner } from '../interfaces';
5
5
  import * as i0 from "@angular/core";
6
6
  export declare class FsForm {
7
7
  private _formDirectiveStore;
8
8
  private _dialog;
9
- registerFormDirective(routeComponent: Type<any>, directive: FsFormDirective): void;
10
- getFormDirectives(routeComponent: any): FsFormDirective[];
9
+ registerFormDirective(routeComponent: Type<any>, directive: FsFormOwner): void;
10
+ getFormDirectives(routeComponent: any): FsFormOwner[];
11
11
  removeFormDirective(routeComponent: any): void;
12
- hasChanges(form: FsFormDirective): boolean;
13
- confirmUnsaved(form: FsFormDirective): Observable<ConfirmResult>;
12
+ hasChanges(form: FsFormOwner): boolean;
13
+ confirmUnsaved(form: FsFormOwner): Observable<ConfirmResult>;
14
14
  static ɵfac: i0.ɵɵFactoryDeclaration<FsForm, never>;
15
15
  static ɵprov: i0.ɵɵInjectableDeclaration<FsForm>;
16
16
  }