@bcweed/dynamic-form-lib 0.0.3 → 0.0.4

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 (66) hide show
  1. package/.editorconfig +17 -0
  2. package/.postcssrc.json +5 -0
  3. package/.vscode/extensions.json +4 -0
  4. package/.vscode/launch.json +20 -0
  5. package/.vscode/tasks.json +42 -0
  6. package/AngularDynamicFormLibrary.esproj +14 -0
  7. package/CHANGELOG.md +16 -0
  8. package/README.md +15 -19
  9. package/angular.json +169 -0
  10. package/aspnetcore-https.js +37 -0
  11. package/karma.conf.js +44 -0
  12. package/obj/Debug/AngularDynamicFormLibrary.esproj.CoreCompileInputs.cache +0 -0
  13. package/obj/Debug/AngularDynamicFormLibrary.esproj.FileListAbsolute.txt +1 -0
  14. package/obj/Debug/package.g.props +56 -0
  15. package/package.json +65 -37
  16. package/postcss.config.js +6 -0
  17. package/projects/dynamic-form-lib/.postcssrc.json +5 -0
  18. package/projects/dynamic-form-lib/README.md +63 -0
  19. package/projects/dynamic-form-lib/ng-package.json +10 -0
  20. package/projects/dynamic-form-lib/package.json +27 -0
  21. package/projects/dynamic-form-lib/src/lib/README.md +424 -0
  22. package/projects/dynamic-form-lib/src/lib/SUMMARY.md +159 -0
  23. package/projects/dynamic-form-lib/src/lib/directives/dynamic-ref-directive.ts +13 -0
  24. package/projects/dynamic-form-lib/src/lib/dynamic-form-demo/dynamic-form-demo.component.html +75 -0
  25. package/projects/dynamic-form-lib/src/lib/dynamic-form-demo/dynamic-form-demo.component.scss +127 -0
  26. package/projects/dynamic-form-lib/src/lib/dynamic-form-demo/dynamic-form-demo.component.ts +50 -0
  27. package/projects/dynamic-form-lib/src/lib/dynamic-form-field/dynamic-form-field.component.html +234 -0
  28. package/projects/dynamic-form-lib/src/lib/dynamic-form-field/dynamic-form-field.component.scss +315 -0
  29. package/projects/dynamic-form-lib/src/lib/dynamic-form-field/dynamic-form-field.component.ts +233 -0
  30. package/projects/dynamic-form-lib/src/lib/dynamic-form.component.html +137 -0
  31. package/projects/dynamic-form-lib/src/lib/dynamic-form.component.scss +141 -0
  32. package/projects/dynamic-form-lib/src/lib/dynamic-form.component.ts +366 -0
  33. package/projects/dynamic-form-lib/src/lib/helpers/component-helper.ts +54 -0
  34. package/projects/dynamic-form-lib/src/lib/index.ts +10 -0
  35. package/projects/dynamic-form-lib/src/lib/models/dynamic-form-interfaces.ts +117 -0
  36. package/projects/dynamic-form-lib/src/lib/services/dynamic-form.service.spec.ts +302 -0
  37. package/projects/dynamic-form-lib/src/lib/services/dynamic-form.service.ts +325 -0
  38. package/projects/dynamic-form-lib/src/lib/style.scss +3 -0
  39. package/projects/dynamic-form-lib/src/lib/tailwind-output.css +0 -0
  40. package/projects/dynamic-form-lib/src/lib/validators/compare-validator.ts +26 -0
  41. package/projects/dynamic-form-lib/src/public-api.css +1 -0
  42. package/projects/dynamic-form-lib/src/public-api.ts +10 -0
  43. package/projects/dynamic-form-lib/tailwind.config.js +10 -0
  44. package/projects/dynamic-form-lib/tsconfig.lib.json +15 -0
  45. package/projects/dynamic-form-lib/tsconfig.lib.prod.json +11 -0
  46. package/projects/dynamic-form-lib/tsconfig.spec.json +15 -0
  47. package/public/favicon.ico +0 -0
  48. package/src/app/app-routing.module.ts +10 -0
  49. package/src/app/app.component.css +0 -0
  50. package/src/app/app.component.html +18 -0
  51. package/src/app/app.component.spec.ts +35 -0
  52. package/src/app/app.component.ts +1038 -0
  53. package/src/app/app.config.ts +45 -0
  54. package/src/app/app.module.ts +46 -0
  55. package/src/app/app.routes.ts +8 -0
  56. package/src/index.html +13 -0
  57. package/src/main.ts +16 -0
  58. package/src/styles.css +2 -0
  59. package/tailwind.config.js +10 -0
  60. package/tsconfig.app.json +15 -0
  61. package/tsconfig.json +32 -0
  62. package/tsconfig.spec.json +15 -0
  63. package/fesm2022/bcweed-dynamic-form-lib.mjs +0 -938
  64. package/fesm2022/bcweed-dynamic-form-lib.mjs.map +0 -1
  65. package/index.d.ts +0 -254
  66. /package/{src → projects/dynamic-form-lib/src}/lib/style.css +0 -0
@@ -0,0 +1,315 @@
1
+ .p-overlay-mask {
2
+ z-index: 10000 !important;
3
+ }
4
+
5
+ .p-drawer .p-drawer.form-pop-info {
6
+ z-index: 10000 !important;
7
+
8
+ }
9
+ .p-drawer-right, .p-drawer.form-pop-info.p-drawer-right {
10
+ top: 65px;
11
+ }
12
+ p-message .p-message.light-font .p-message-text{
13
+ font-weight:normal;
14
+ }
15
+
16
+ .form-group {
17
+ margin-bottom: 1rem;
18
+ position: relative;
19
+ transition: all 0.3s ease;
20
+ display: flex;
21
+ flex-wrap: wrap;
22
+ gap: 0.75rem;
23
+
24
+ .left-pre-input {
25
+ display: flex;
26
+ flex-direction: column;
27
+ justify-content: flex-end;
28
+ align-items: flex-end;
29
+ flex-basis: 40%;
30
+ flex-shrink: 0;
31
+ flex-grow: 0;
32
+
33
+ .left-pre-input-text {
34
+ text-align: right;
35
+ width: 100%;
36
+ margin-bottom: 10px;
37
+ font-weight: 600;
38
+ }
39
+ }
40
+
41
+ .input-container {
42
+ flex-grow: 1;
43
+ flex-shrink: 1;
44
+ min-width: 0;
45
+ }
46
+
47
+ .label-row {
48
+ display: flex;
49
+ justify-content: space-between;
50
+ align-items: start;
51
+ margin-bottom: 0.5rem;
52
+ }
53
+
54
+ .help-icons {
55
+ display: flex;
56
+ gap: 0.5rem;
57
+ margin-left: 0.5rem;
58
+
59
+ i {
60
+ cursor: pointer;
61
+ color: #6c757d;
62
+ transition: color 0.2s ease;
63
+
64
+ &:hover {
65
+ color: #007bff;
66
+ }
67
+ }
68
+ }
69
+
70
+ .control-label {
71
+ display: block;
72
+ /*margin-bottom: 0.5rem;*/
73
+ font-weight: 500;
74
+ color: #333;
75
+
76
+ .required-indicator {
77
+ color: #dc3545;
78
+ margin-left: 0.25rem;
79
+ }
80
+ }
81
+
82
+ .form-control {
83
+ width: 100%;
84
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
85
+ }
86
+
87
+ .field-hint {
88
+ display: block;
89
+ margin-top: 0.25rem;
90
+ font-size: 0.875rem;
91
+ color: #6c757d;
92
+ }
93
+ // Checkbox wrapper
94
+ .checkbox-wrapper {
95
+ padding: 0.5rem 0;
96
+ }
97
+ // Radio group
98
+ .radio-group {
99
+ display: flex;
100
+ flex-direction: column;
101
+ gap: 0.75rem;
102
+
103
+ .radio-option {
104
+ display: flex;
105
+ align-items: center;
106
+ /*gap: 0.5rem;*/
107
+ flex-wrap: wrap;
108
+
109
+ .radio-label {
110
+ margin: 0;
111
+ cursor: pointer;
112
+ font-weight: normal;
113
+ }
114
+
115
+ .radion-hint {
116
+ flex-basis: 100%;
117
+ width: 100%;
118
+ display: block;
119
+ /*margin-top: 0.25rem;*/
120
+ margin-left: 36px;
121
+ font-size: 0.875rem;
122
+ color: #6c757d;
123
+ }
124
+
125
+ .radio-message-container {
126
+ flex-basis: 100%;
127
+ width: 100%;
128
+ margin-top: 0.25rem;
129
+ margin-left: 36px;
130
+ }
131
+ }
132
+ }
133
+ // Error messages
134
+ .error-messages {
135
+ margin-top: 0.5rem;
136
+ flex-basis: 100%;
137
+ width: 100%;
138
+ animation: slideDown 0.3s ease;
139
+
140
+ ::ng-deep .p-message {
141
+ margin-bottom: 0.25rem;
142
+
143
+ &:last-child {
144
+ margin-bottom: 0;
145
+ }
146
+ }
147
+ }
148
+ // Valid indicator
149
+ .valid-indicator, .valid-indicator-select, .valid-indicator-calendar {
150
+ position: absolute;
151
+ color: #28a745;
152
+ font-size: 1.2rem;
153
+ animation: fadeIn 0.3s ease;
154
+
155
+ i {
156
+ display: block;
157
+ }
158
+ }
159
+
160
+ .valid-indicator {
161
+ right: 10px;
162
+ top: 38px;
163
+ }
164
+
165
+ .valid-indicator-select {
166
+ right: 80px;
167
+ top: 38px;
168
+ }
169
+
170
+ .valid-indicator-calendar {
171
+ right: 80px;
172
+ top: 38px;
173
+ }
174
+ //fix padding
175
+ .p-select,
176
+ ::ng-deep .p-datepicker,
177
+ .p-inputnumber {
178
+ padding: 0;
179
+ }
180
+ //fix number border
181
+ .p-datepicker > span > input,
182
+ .p-inputnumber {
183
+ border: none !important;
184
+ }
185
+ // Field states
186
+ &.field-error {
187
+ .form-control,
188
+ ::ng-deep .p-inputtext,
189
+ ::ng-deep .p-select,
190
+ ::ng-deep .p-datepicker,
191
+ ::ng-deep .p-inputnumber input {
192
+ border-color: #dc3545 !important;
193
+
194
+ &:focus {
195
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
196
+ }
197
+ }
198
+
199
+ .p-datepicker > span > input {
200
+ border: none !important;
201
+ }
202
+
203
+ .control-label {
204
+ color: #dc3545;
205
+ }
206
+ }
207
+
208
+ &.field-valid {
209
+ .form-control,
210
+ ::ng-deep .p-inputtext,
211
+ ::ng-deep .p-select,
212
+ ::ng-deep .p-datepicker,
213
+ ::ng-deep .p-inputnumber input {
214
+ border-color: #28a745;
215
+
216
+ &:focus {
217
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
218
+ }
219
+ }
220
+
221
+ .p-datepicker > span > input {
222
+ border: none !important;
223
+ }
224
+ }
225
+
226
+ &.field-disabled {
227
+ opacity: 0.6;
228
+ pointer-events: none;
229
+
230
+ .control-label {
231
+ color: #6c757d;
232
+ }
233
+ }
234
+
235
+ &.field-required {
236
+ // Additional styling for required fields if needed
237
+ }
238
+ }
239
+
240
+ .form-group.field-error {
241
+ padding: 12px;
242
+ border: 1px solid #dc3545;
243
+ background-color: var(--p-red-100);
244
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
245
+ border-radius: 10px;
246
+ }
247
+
248
+ // Animations
249
+ @keyframes slideDown {
250
+ from {
251
+ opacity: 0;
252
+ transform: translateY(-10px);
253
+ }
254
+
255
+ to {
256
+ opacity: 1;
257
+ transform: translateY(0);
258
+ }
259
+ }
260
+
261
+ @keyframes fadeIn {
262
+ from {
263
+ opacity: 0;
264
+ }
265
+
266
+ to {
267
+ opacity: 1;
268
+ }
269
+ }
270
+
271
+ // PrimeNG component overrides for consistent styling
272
+ ::ng-deep {
273
+ .p-inputtext,
274
+ .p-select,
275
+ .p-datepicker .p-inputtext,
276
+ .p-inputnumber-input {
277
+ width: 100%;
278
+ }
279
+
280
+ .p-select {
281
+ display: flex;
282
+ }
283
+
284
+ .p-datepicker {
285
+ width: 100%;
286
+
287
+ .p-inputtext {
288
+ width: 100%;
289
+ }
290
+ }
291
+
292
+ .p-inputnumber {
293
+ width: 100%;
294
+ }
295
+
296
+ .p-checkbox {
297
+ margin-right: 0.5rem;
298
+ }
299
+
300
+ .p-radiobutton {
301
+ margin-right: 0.5rem;
302
+ }
303
+ }
304
+
305
+ // Responsive adjustments
306
+ @media (max-width: 768px) {
307
+ .form-group {
308
+ .radio-group {
309
+ .radio-option {
310
+ flex-direction: row;
311
+ align-items: flex-start;
312
+ }
313
+ }
314
+ }
315
+ }
@@ -0,0 +1,233 @@
1
+ import { Component, ElementRef, Input, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormGroup, NgForm, ReactiveFormsModule } from '@angular/forms';
4
+ import { DynamicFormField, DynamicFormOption } from '../models/dynamic-form-interfaces';
5
+ import { InputTextModule } from 'primeng/inputtext';
6
+ import { TextareaModule } from 'primeng/textarea';
7
+ //import { InputTextarea } from 'primeng/inputtextarea';
8
+ import { InputNumberModule } from 'primeng/inputnumber';
9
+ import { CheckboxChangeEvent, CheckboxModule } from 'primeng/checkbox';
10
+ import { RadioButtonModule, RadioButtonClickEvent, RadioButton } from 'primeng/radiobutton';
11
+ import { SelectModule } from 'primeng/select';
12
+ //import { DropdownModule } from 'primeng/dropdown';
13
+ import { DatePickerModule } from 'primeng/datepicker';
14
+ //import { CalendarModule } from 'primeng/calendar';
15
+ import { MessageModule } from 'primeng/message';
16
+ import { DynamicRefDirective } from '../directives/dynamic-ref-directive';
17
+ import { TooltipModule } from 'primeng/tooltip';
18
+ import { ScrollPanelModule } from 'primeng/scrollpanel';
19
+ import { PopoverModule } from 'primeng/popover';
20
+ import { DrawerModule } from 'primeng/drawer';
21
+ import { InputMaskModule } from 'primeng/inputmask';
22
+ import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
23
+
24
+ @Component({
25
+ selector: 'app-dynamic-form-field',
26
+ standalone: true,
27
+ imports: [
28
+ CommonModule,
29
+ ReactiveFormsModule,
30
+ InputTextModule,
31
+ TextareaModule,
32
+ //InputTextarea,
33
+ InputNumberModule,
34
+ CheckboxModule,
35
+ RadioButtonModule,
36
+ SelectModule,
37
+ //DropdownModule,
38
+ DatePickerModule,
39
+ //CalendarModule,
40
+ MessageModule,
41
+ TooltipModule,
42
+ DynamicRefDirective,
43
+ ScrollPanelModule,
44
+ PopoverModule,
45
+ DrawerModule,
46
+ InputMaskModule
47
+ ],
48
+ templateUrl: './dynamic-form-field.component.html',
49
+ styleUrls: ['./dynamic-form-field.component.scss']
50
+ })
51
+ export class DynamicFormFieldComponent implements OnInit {
52
+ @Input() field!: DynamicFormField;
53
+ @Input() form!: FormGroup;
54
+ @Input() errors: string[] = [];
55
+ @Input() allowHelpOverlay = false;
56
+ @Input() allowHelpSideBar = false;
57
+ @ViewChild(DynamicRefDirective) ref!: DynamicRefDirective;
58
+ elementRef: ElementRef | null = null;
59
+ @ViewChild(RadioButton) radioButton?: RadioButton;
60
+ helpSideBarVisible = false;
61
+ shouldDisable = true;
62
+ isExpanded = false;
63
+ isSmallMedia = false;
64
+ isMediumMedia = false;
65
+
66
+ constructor(private responsive: BreakpointObserver) { }
67
+
68
+ ngOnInit(): void {
69
+ this.responsive.observe([Breakpoints.Medium, Breakpoints.Small, Breakpoints.XSmall])
70
+ .subscribe(result => {
71
+
72
+
73
+ if (result.matches) {
74
+ this.isSmallMedia = true;
75
+
76
+ }
77
+ else {
78
+ this.isSmallMedia = false;
79
+
80
+ }
81
+ });
82
+
83
+ if (!this.field || !this.form) {
84
+ console.error('DynamicFormFieldComponent requires field and form inputs');
85
+
86
+ }
87
+ }
88
+ ngAfterViewInit(): void {
89
+ if (this.radioButton) {
90
+ this.elementRef = this.radioButton.inputViewChild;
91
+ }
92
+ if (this.ref) {
93
+ this.elementRef = this.ref.el;
94
+ }
95
+ if ((this.field.conditionalDisabled && this.field.conditionalDisabled()) || this.field.disabled) {
96
+ this.form.controls[this.field.id].disable();
97
+ }
98
+ }
99
+ get isValid(): boolean {
100
+ const control = this.form.get(this.field.id);
101
+ return control ? control.valid : true;
102
+ }
103
+
104
+ get isTouched(): boolean {
105
+ const control = this.form.get(this.field.id);
106
+ return control ? control.touched : false;
107
+ }
108
+
109
+ get isDirty(): boolean {
110
+ const control = this.form.get(this.field.id);
111
+ return control ? control.dirty : false;
112
+ }
113
+
114
+ get showError(): boolean {
115
+ return !this.isValid && (this.isTouched || this.isDirty);
116
+ }
117
+
118
+ get fieldClasses(): string {
119
+ const classes = ['form-group'];
120
+
121
+ if (this.showError) {
122
+ if (!this.field.disabled) {
123
+ classes.push('field-error');
124
+ }
125
+ } else if (this.isValid && (this.isTouched || this.isDirty)) {
126
+ classes.push('field-valid');
127
+ }
128
+
129
+ if (this.field.disabled) {
130
+ classes.push('field-disabled');
131
+ }
132
+
133
+ if (this.field.required) {
134
+ classes.push('field-required');
135
+ }
136
+
137
+ return classes.join(' ');
138
+ }
139
+
140
+ get successIndicatorClass():string {
141
+
142
+ if (this.field.type == 'select') {
143
+ return "valid-indicator-select";
144
+ }
145
+ else if (this.field.type == 'date') {
146
+ return "valid-indicator-calendar";
147
+ }
148
+ else {
149
+ return "valid-indicator";
150
+
151
+ }
152
+ }
153
+ get controlName(): string {
154
+ return this.field.id;
155
+ }
156
+
157
+ focusOn() {
158
+ if (this.elementRef) {
159
+ this.elementRef.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
160
+ this.elementRef.nativeElement.focus();
161
+ }
162
+ }
163
+ onBlur(): void {
164
+ const control = this.form.get(this.field.id);
165
+ if (control) {
166
+ control.markAsTouched();
167
+ }
168
+ }
169
+
170
+ displayRadioError(option: DynamicFormOption) {
171
+ if (option.displayError && typeof option.displayError === 'function') {
172
+ return option.displayError();
173
+ }
174
+ return false;
175
+ }
176
+
177
+ onClick(event: Event): void {
178
+
179
+ if (typeof this.field.onClick === 'function') {
180
+
181
+ this.field.onClick((event.target as HTMLInputElement).value, this.form);
182
+ }
183
+ }
184
+ onChange(event: Event): void {
185
+
186
+ if (typeof this.field.onChange === 'function') {
187
+
188
+ this.field.onChange((event.target as HTMLInputElement).value, this.form);
189
+ }
190
+ }
191
+ onCheckboxChange(event: CheckboxChangeEvent): void {
192
+
193
+ if (typeof this.field.onChange === 'function') {
194
+
195
+ this.field.onChange((event.checked ? true : false), this.form);
196
+ }
197
+ }
198
+ labelWidthStyle(): string {
199
+ return this.isSmallMedia ? '100%' : this.field.labelWidth ? this.field.labelWidth : '100%';
200
+ }
201
+ fieldWidthStyle(): string {
202
+ return this.isSmallMedia ? '100%' : this.field.fieldWidth ? this.field.fieldWidth : '100%';
203
+ }
204
+ inputWidthStyle(): string {
205
+ return this.isSmallMedia ? '100%' : this.field.inputWidth ? this.field.inputWidth : '100%';
206
+ }
207
+ trackByFn(index: number, item: any): any {
208
+ return item.value;
209
+ }
210
+ get getMinValue(): number | null {
211
+ if (this.field.type === 'number' && this.field.min !== undefined) {
212
+ return this.field.min;
213
+ }
214
+ return null;
215
+ }
216
+
217
+ get getMaxValue(): number | null {
218
+ if (this.field.type === 'number' && this.field.max !== undefined) {
219
+ return this.field.max;
220
+ }
221
+ return null;
222
+ }
223
+ get getDecimalPlace(): number {
224
+ if (this.field.type === 'number' && this.field.decimals !== undefined) {
225
+ return this.field.decimals;
226
+ }
227
+ return 0;
228
+ }
229
+ isFieldDisabled(): any {
230
+ const t = (this.field.conditionalDisabled && this.field.conditionalDisabled()) ? '' : null;
231
+ return t;
232
+ }
233
+ }
@@ -0,0 +1,137 @@
1
+ @if (config) {
2
+ <div class="dynamic-form-container">
3
+ @if (config.title || config.description) {
4
+ <div class="form-title">
5
+ <div class="title-container">
6
+ @if (config.title) {
7
+ <h4>{{ config.title }}</h4>
8
+ }
9
+ @if (config.description) {
10
+ <p class="form-description">{{ config.description }}</p>
11
+ }
12
+ <hr class="title-subline" />
13
+ </div>
14
+ </div>
15
+ }
16
+ <form [formGroup]="form" (ngSubmit)="onSubmit()" novalidate>
17
+ <div *ngIf="config.preInfo" class="message-container">
18
+ <p-message styleClass="light-font" severity="info">
19
+ <div [innerHTML]="config.preInfo"></div>
20
+ </p-message>
21
+ </div>
22
+ <div *ngIf="config.preWarning" class="message-container">
23
+ <p-message styleClass="light-font" severity="warn">
24
+ <div [innerHTML]="config.preWarning"></div>
25
+ </p-message>
26
+ </div>
27
+
28
+ <ng-container *ngFor="let frame of sortedFrames">
29
+ <div [ngClass]="frame.cssClass" *ngIf="isFrameVisible(frame)">
30
+ <div [ngClass]="frame.innerFrameCssClass">
31
+ <div *ngIf="frame.title" [ngClass]="frame.titleContainerCssClass">
32
+ <span *ngIf="frame.titlePrefix" [ngClass]="frame.titlePrefixCssClass">{{frame.titlePrefix}}</span>
33
+ <h3 [ngClass]="frame.titleCssClass">{{frame.title}}</h3>
34
+ </div>
35
+ <div *ngIf="frame.description" class="frame-description">
36
+ <p-message styleClass="light-font" severity="info">
37
+ <div [innerHTML]="frame.description"></div>
38
+ </p-message>
39
+ </div>
40
+
41
+ <ng-container *ngFor="let section of frame.sections">
42
+ <div class="section-wrapper" *ngIf="isSectionVisible(section)">
43
+ <div class="section-content">
44
+
45
+ <h5 *ngIf="section.title != null" class="section-title">{{section.title}}</h5>
46
+ <div *ngIf="section.preInfo" class="message-container">
47
+ <p-message styleClass="light-font" severity="info">
48
+ <div [innerHTML]="section.preInfo"></div>
49
+ </p-message>
50
+ </div>
51
+ <div *ngIf="section.preWarning" class="message-container">
52
+ <p-message styleClass="light-font" severity="warn">
53
+ <div [innerHTML]="section.preWarning"></div>
54
+ </p-message>
55
+ </div>
56
+
57
+ <div class="fields-wrapper">
58
+ <div class="fields-grid">
59
+ <ng-container *ngFor="let field of section.fields">
60
+ <ng-container *ngIf="field.type == 'hidden'" [formGroup]="form">
61
+ <input type="hidden" [formControlName]="field.id" />
62
+
63
+ </ng-container>
64
+ <ng-container *ngIf="field.type != 'hidden'">
65
+
66
+ <div class="field-container" [ngClass]="field.cssClass" *ngIf="isFieldVisible(field)">
67
+ <app-dynamic-form-field [field]="field"
68
+ [form]="form"
69
+ [errors]="getFieldErrors(field.id)"
70
+ [allowHelpOverlay]="allowHelpOverlay"
71
+ [allowHelpSideBar]="allowHelpSideBar">
72
+ </app-dynamic-form-field>
73
+
74
+ </div>
75
+ </ng-container>
76
+
77
+ </ng-container>
78
+ </div>
79
+ </div>
80
+
81
+ <div *ngIf="section.postInfo" class="message-container">
82
+ <p-message styleClass="light-font" severity="info">
83
+ <div [innerHTML]="section.postInfo"></div>
84
+ </p-message>
85
+ </div>
86
+ <div *ngIf="section.postWarning" class="message-container">
87
+ <p-message styleClass="light-font" severity="warn">
88
+ <div [innerHTML]="section.postWarning"></div>
89
+ </p-message>
90
+ </div>
91
+
92
+
93
+ </div>
94
+ </div>
95
+ </ng-container>
96
+ </div>
97
+ </div>
98
+ </ng-container>
99
+
100
+
101
+ <ng-content></ng-content>
102
+ <div id="buttoncont" class="button-container">
103
+ <div class="button-group">
104
+ @if (showCancelButton()) {
105
+ <button pButton
106
+ type="button"
107
+ class="btn-cancel"
108
+ icon="{{config.cancelIcon ? config.cancelIcon : 'pi pi-times'}}"
109
+ iconPos="left"
110
+ [label]="cancelLabel"
111
+ [disabled]="formState.isSubmitting"
112
+ (click)="onCancel()">
113
+ </button>
114
+ }
115
+ @if (showSubmitButton()) {
116
+ <button pButton
117
+ type="submit"
118
+ class=""
119
+ icon="{{config.submitIcon ? config.submitIcon : 'pi pi-check'}}"
120
+ iconPos="right"
121
+ [label]="submitLabel"
122
+ [disabled]="formState.isSubmitting"
123
+ [loading]="formState.isSubmitting">
124
+ </button>
125
+ }
126
+ </div>
127
+ </div>
128
+ <div *ngIf="config.postInfo" class="message-container">
129
+ <p-message styleClass="light-font" severity="info">{{config.postInfo}}</p-message>
130
+ </div>
131
+ <div *ngIf="config.postWarning" class="message-container">
132
+ <p-message styleClass="light-font" severity="warn">{{config.postWarning}}</p-message>
133
+ </div>
134
+
135
+ </form>
136
+ </div>
137
+ }