@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.
- package/app/components/form-dialog-actions/form-dialog-actions.component.d.ts +14 -2
- package/app/directives/button.directive.d.ts +1 -1
- package/app/directives/form/form.directive.d.ts +87 -29
- package/app/directives/form-base/form-base.directive.d.ts +73 -5
- package/app/directives/form-container/form-container.directive.d.ts +80 -0
- package/app/directives/form-container/index.d.ts +1 -0
- package/app/directives/index.d.ts +1 -1
- package/app/fs-form.module.d.ts +2 -2
- package/app/interfaces/form-owner.d.ts +17 -0
- package/app/interfaces/index.d.ts +1 -0
- package/app/services/fsform.service.d.ts +5 -5
- package/esm2022/app/components/form-dialog-actions/form-dialog-actions.component.mjs +41 -17
- package/esm2022/app/directives/button.directive.mjs +13 -8
- package/esm2022/app/directives/form/form.directive.mjs +238 -241
- package/esm2022/app/directives/form-base/form-base.directive.mjs +239 -6
- package/esm2022/app/directives/form-container/form-container.directive.mjs +164 -0
- package/esm2022/app/directives/form-container/index.mjs +2 -0
- package/esm2022/app/directives/index.mjs +2 -2
- package/esm2022/app/fs-form.module.mjs +6 -6
- package/esm2022/app/guards/form-deactivate.guard.mjs +1 -1
- package/esm2022/app/interfaces/form-owner.mjs +2 -0
- package/esm2022/app/interfaces/index.mjs +2 -1
- package/esm2022/app/services/fsform.service.mjs +10 -7
- package/esm2022/public_api.mjs +2 -2
- package/fesm2022/firestitch-form.mjs +702 -317
- package/fesm2022/firestitch-form.mjs.map +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +2 -1
- package/app/directives/form-group/form-group.directive.d.ts +0 -15
- package/app/directives/form-group/index.d.ts +0 -1
- package/esm2022/app/directives/form-group/form-group.directive.mjs +0 -35
- 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
|
-
|
|
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>;
|
|
@@ -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 {
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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; }; "
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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';
|
package/app/fs-form.module.d.ts
CHANGED
|
@@ -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-
|
|
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.
|
|
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
|
+
}
|
|
@@ -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:
|
|
10
|
-
getFormDirectives(routeComponent: any):
|
|
9
|
+
registerFormDirective(routeComponent: Type<any>, directive: FsFormOwner): void;
|
|
10
|
+
getFormDirectives(routeComponent: any): FsFormOwner[];
|
|
11
11
|
removeFormDirective(routeComponent: any): void;
|
|
12
|
-
hasChanges(form:
|
|
13
|
-
confirmUnsaved(form:
|
|
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
|
}
|