@firestitch/form 18.0.27 → 18.0.29
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/directives/button.directive.d.ts +6 -1
- package/esm2022/app/components/form-dialog-actions/form-dialog-actions.component.mjs +2 -2
- package/esm2022/app/directives/button.directive.mjs +33 -8
- package/esm2022/app/directives/form/form.directive.mjs +12 -2
- package/esm2022/app/directives/form-base/form-base.directive.mjs +5 -1
- package/fesm2022/firestitch-form.mjs +48 -9
- package/fesm2022/firestitch-form.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -263,6 +263,9 @@ class FsFormBaseDirective {
|
|
|
263
263
|
...this._buttons.toArray(),
|
|
264
264
|
button,
|
|
265
265
|
]);
|
|
266
|
+
// QueryList.reset() does not emit `changes`; notify so subscribers (e.g. the
|
|
267
|
+
// form's dirty-submit-button tracking) react to buttons being registered.
|
|
268
|
+
this._buttons.notifyOnChanges();
|
|
266
269
|
}
|
|
267
270
|
removeButton(button) {
|
|
268
271
|
if (this._activeSubmitButton === button) {
|
|
@@ -272,6 +275,7 @@ class FsFormBaseDirective {
|
|
|
272
275
|
...this._buttons.toArray()
|
|
273
276
|
.filter((item) => (button !== item)),
|
|
274
277
|
]);
|
|
278
|
+
this._buttons.notifyOnChanges();
|
|
275
279
|
}
|
|
276
280
|
_registerConfirmTabs() {
|
|
277
281
|
this._registerConfirmTabGroups(this._tabGroups.toArray());
|
|
@@ -823,10 +827,20 @@ class FsFormDirective extends FsFormBaseDirective {
|
|
|
823
827
|
.buttons.changes
|
|
824
828
|
.pipe(takeUntil(this.destroy$))
|
|
825
829
|
.subscribe(() => {
|
|
826
|
-
|
|
830
|
+
// Buttons (de)register during change detection (their ngOnInit/ngOnDestroy),
|
|
831
|
+
// so defer to a microtask to update the disabled state outside that pass and
|
|
832
|
+
// avoid ExpressionChangedAfterItHasBeenChecked on the button's disabled binding.
|
|
833
|
+
Promise.resolve().then(() => this._updateDirtySubmitButtons());
|
|
827
834
|
});
|
|
835
|
+
// The initial content buttons register (addButton) before the subscription above
|
|
836
|
+
// exists, so their `changes` emission is missed. Apply the initial pristine/dirty
|
|
837
|
+
// disabled state once, deferred so it runs after the current change-detection pass.
|
|
838
|
+
Promise.resolve().then(() => this._updateDirtySubmitButtons());
|
|
828
839
|
}
|
|
829
840
|
_updateDirtySubmitButtons() {
|
|
841
|
+
if (!this.ngForm) {
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
830
844
|
this._getFormGroup()
|
|
831
845
|
.buttons
|
|
832
846
|
.filter((button) => button.submit)
|
|
@@ -957,8 +971,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
957
971
|
class FsButtonDirective {
|
|
958
972
|
name;
|
|
959
973
|
dirtySubmit = true;
|
|
974
|
+
set submitDisabled(value) {
|
|
975
|
+
this._submitDisabled = value;
|
|
976
|
+
this._applyDisabled();
|
|
977
|
+
}
|
|
978
|
+
get submitDisabled() {
|
|
979
|
+
return this._submitDisabled;
|
|
980
|
+
}
|
|
960
981
|
transitionStyle = null;
|
|
961
982
|
submit = false;
|
|
983
|
+
_submitDisabled = false;
|
|
984
|
+
_formDisabled = false;
|
|
962
985
|
_previousDisabled = false;
|
|
963
986
|
_destroy$ = new Subject();
|
|
964
987
|
_formGroup = inject(FsFormGroupDirective, { optional: true });
|
|
@@ -969,7 +992,12 @@ class FsButtonDirective {
|
|
|
969
992
|
_formBase;
|
|
970
993
|
ngOnInit() {
|
|
971
994
|
this.submit = this._elementRef.nativeElement.getAttribute('type') === 'submit';
|
|
972
|
-
|
|
995
|
+
// Prefer the enclosing form group over the form: the form's own button
|
|
996
|
+
// management (dirty-submit tracking, activeSubmitButton, reset) resolves its
|
|
997
|
+
// registry via `_formGroup || this`, so buttons must register with the same
|
|
998
|
+
// owner. Registering with the form while the form reads the group leaves the
|
|
999
|
+
// group's button list empty and the submit button never gets dirty-disabled.
|
|
1000
|
+
this._formBase = this._formGroup || this._form;
|
|
973
1001
|
if (this._formBase) {
|
|
974
1002
|
this._formBase.addButton(this);
|
|
975
1003
|
if (this.submit) {
|
|
@@ -983,7 +1011,7 @@ class FsButtonDirective {
|
|
|
983
1011
|
this.transitionStyle = 'none';
|
|
984
1012
|
setTimeout(() => {
|
|
985
1013
|
this.transitionStyle = null;
|
|
986
|
-
this._cdRef.
|
|
1014
|
+
this._cdRef.markForCheck();
|
|
987
1015
|
}, 500);
|
|
988
1016
|
}
|
|
989
1017
|
}
|
|
@@ -991,16 +1019,16 @@ class FsButtonDirective {
|
|
|
991
1019
|
disable() {
|
|
992
1020
|
if (this._matButton && !this._formBase.activeSubmitButton) {
|
|
993
1021
|
this._previousDisabled = this._matButton.disabled;
|
|
994
|
-
this.
|
|
1022
|
+
this._formDisabled = true;
|
|
995
1023
|
this._matButton.disableRipple = true;
|
|
996
|
-
this.
|
|
1024
|
+
this._applyDisabled();
|
|
997
1025
|
}
|
|
998
1026
|
}
|
|
999
1027
|
enable() {
|
|
1000
1028
|
if (this._matButton) {
|
|
1001
|
-
this.
|
|
1029
|
+
this._formDisabled = false;
|
|
1002
1030
|
this._matButton.disableRipple = true;
|
|
1003
|
-
this.
|
|
1031
|
+
this._applyDisabled();
|
|
1004
1032
|
}
|
|
1005
1033
|
}
|
|
1006
1034
|
process() {
|
|
@@ -1048,6 +1076,15 @@ class FsButtonDirective {
|
|
|
1048
1076
|
this._destroy$.complete();
|
|
1049
1077
|
this._formBase?.removeButton(this);
|
|
1050
1078
|
}
|
|
1079
|
+
// Effective disabled combines the consumer-controlled submitDisabled input with
|
|
1080
|
+
// the form's submit-lifecycle state, so form enable/disable never clobbers an
|
|
1081
|
+
// explicit [submitDisabled] and the two channels stay independent.
|
|
1082
|
+
_applyDisabled() {
|
|
1083
|
+
if (this._matButton) {
|
|
1084
|
+
this._matButton.disabled = this._submitDisabled || this._formDisabled;
|
|
1085
|
+
this._cdRef.markForCheck();
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1051
1088
|
_resetClass() {
|
|
1052
1089
|
this.element.classList
|
|
1053
1090
|
.remove('fs-form-submit-button-success', 'fs-form-submit-button-error', 'fs-form-submit-button-process');
|
|
@@ -1078,7 +1115,7 @@ class FsButtonDirective {
|
|
|
1078
1115
|
}
|
|
1079
1116
|
}
|
|
1080
1117
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsButtonDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1081
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.7", type: FsButtonDirective, isStandalone: true, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: { name: "name", dirtySubmit: "dirtySubmit" }, host: { properties: { "style.transition": "this.transitionStyle" } }, ngImport: i0 });
|
|
1118
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.7", type: FsButtonDirective, isStandalone: true, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: { name: "name", dirtySubmit: "dirtySubmit", submitDisabled: "submitDisabled" }, host: { properties: { "style.transition": "this.transitionStyle" } }, ngImport: i0 });
|
|
1082
1119
|
}
|
|
1083
1120
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsButtonDirective, decorators: [{
|
|
1084
1121
|
type: Directive,
|
|
@@ -1090,6 +1127,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
1090
1127
|
type: Input
|
|
1091
1128
|
}], dirtySubmit: [{
|
|
1092
1129
|
type: Input
|
|
1130
|
+
}], submitDisabled: [{
|
|
1131
|
+
type: Input
|
|
1093
1132
|
}], transitionStyle: [{
|
|
1094
1133
|
type: HostBinding,
|
|
1095
1134
|
args: ['style.transition']
|
|
@@ -1174,7 +1213,7 @@ class FsFormDialogActionsComponent {
|
|
|
1174
1213
|
this._destroy$.complete();
|
|
1175
1214
|
}
|
|
1176
1215
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsFormDialogActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1177
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsFormDialogActionsComponent, isStandalone: true, selector: "fs-form-dialog-actions", inputs: { save: "save", create: "create", close: "close", done: "done", closeData: "closeData", name: "name" }, ngImport: i0, template: "<div\n class=\"form-buttons\"\n [ngClass]=\"{ 'save-create': save || create }\">\n @if (save || create) {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\"\n [name]=\"name\">\n {{ create ? 'Create' : 'Save' }}\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [disabled]=\"close && !dirty && !create\"\n [mat-dialog-close]=\"null\">\n Cancel\n </button>\n }\n @if (done) {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n @if (save || create) {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n }\n @if (close) {\n <button\n mat-button\n type=\"button\"\n class=\"close-button\"\n fsFormDialogClose\n [closeData]=\"closeData\"\n [color]=\"dirty ? 'basic' : 'primary'\">\n Close\n </button>\n }\n @if (!(save || create)) {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n }\n</div>\n<ng-template #content>\n <ng-content></ng-content>\n</ng-template>", styles: [":host{width:100%}.form-buttons.save-create .close-button{float:right}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FsFormDialogCloseDirective, selector: "[fsFormDialogClose],[fs-form-dialog-close]", inputs: ["closeData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1216
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsFormDialogActionsComponent, isStandalone: true, selector: "fs-form-dialog-actions", inputs: { save: "save", create: "create", close: "close", done: "done", closeData: "closeData", name: "name" }, ngImport: i0, template: "<div\n class=\"form-buttons\"\n [ngClass]=\"{ 'save-create': save || create }\">\n @if (save || create) {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\"\n [name]=\"name\">\n {{ create ? 'Create' : 'Save' }}\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [disabled]=\"close && !dirty && !create\"\n [mat-dialog-close]=\"null\">\n Cancel\n </button>\n }\n @if (done) {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n @if (save || create) {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n }\n @if (close) {\n <button\n mat-button\n type=\"button\"\n class=\"close-button\"\n fsFormDialogClose\n [closeData]=\"closeData\"\n [color]=\"dirty ? 'basic' : 'primary'\">\n Close\n </button>\n }\n @if (!(save || create)) {\n <ng-template [ngTemplateOutlet]=\"content\"></ng-template>\n }\n</div>\n<ng-template #content>\n <ng-content></ng-content>\n</ng-template>", styles: [":host{width:100%}.form-buttons.save-create .close-button{float:right}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit", "submitDisabled"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FsFormDialogCloseDirective, selector: "[fsFormDialogClose],[fs-form-dialog-close]", inputs: ["closeData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1178
1217
|
}
|
|
1179
1218
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsFormDialogActionsComponent, decorators: [{
|
|
1180
1219
|
type: Component,
|