@bolttech/form-engine-core 1.0.0-beta.11 → 1.0.0-beta.13

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/index.esm.js CHANGED
@@ -50,7 +50,7 @@ const TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR = /^\$\{(?:[^{}]|\{(?:[^{}]|\
50
50
  const TEMPLATE_REGEX_DELIMITATOR = /\$\{((?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*)\}/g;
51
51
  const TEMPLATE_REGEX_OPERATOR_SPLITTER = /\s*(\|\||&&|!)\s*/g;
52
52
  const TEMPLATE_REGEX_OPERATOR_MATCHER = /^\|\||&&|!$/;
53
- const TEMPLATE_AVALIABLE_SCOPES = ['fields', 'iVars'];
53
+ const TEMPLATE_AVALIABLE_SCOPES = ['fields', 'iVars', 'form'];
54
54
  const ALLOWED_RESET_PROPS_MUTATIONS = ['api', 'apiSchema', 'props', 'validations', 'visibilityConditions', 'resetValues'];
55
55
  const DEFAULT_LOG_VERBOSE = false;
56
56
 
@@ -2495,7 +2495,7 @@ class FormField {
2495
2495
  templateSubject$,
2496
2496
  fieldEventSubject$,
2497
2497
  dataSubject$,
2498
- formValidNotification$,
2498
+ fieldValidNotification$,
2499
2499
  mountSubject$,
2500
2500
  mapper,
2501
2501
  getFormValues,
@@ -2535,7 +2535,7 @@ class FormField {
2535
2535
  this.templateSubject$ = templateSubject$;
2536
2536
  this.fieldEventSubject$ = fieldEventSubject$;
2537
2537
  this.dataSubject$ = dataSubject$;
2538
- this.formValidNotification$ = formValidNotification$;
2538
+ this.fieldValidNotification$ = fieldValidNotification$;
2539
2539
  this.mountSubject$ = mountSubject$;
2540
2540
  this._props = FormField.filterProps(cloneDeep(schemaComponent.props || {}));
2541
2541
  this._metadata = '';
@@ -2554,11 +2554,14 @@ class FormField {
2554
2554
  status: null
2555
2555
  };
2556
2556
  return acc;
2557
- }, {})
2557
+ }, {}),
2558
+ apiState: {
2559
+ loading: false
2560
+ }
2558
2561
  };
2559
2562
  this._errors = {};
2560
2563
  this._mounted = false;
2561
- this._valid = true;
2564
+ this.valid = true;
2562
2565
  this.initializeObservers();
2563
2566
  }
2564
2567
  /**
@@ -2576,9 +2579,6 @@ class FormField {
2576
2579
  if (!this.visibilitySubject$ || this.visibilitySubject$.closed) {
2577
2580
  this.visibilitySubject$ = new SafeSubject(() => this.mounted);
2578
2581
  }
2579
- if (!this.apiSubject$ || this.apiSubject$.closed) {
2580
- this.apiSubject$ = new SafeSubject(() => this.mounted);
2581
- }
2582
2582
  if (!this.propsSubject$ || this.propsSubject$.closed) {
2583
2583
  this.propsSubject$ = new SafeSubject(() => this.mounted);
2584
2584
  }
@@ -2590,7 +2590,7 @@ class FormField {
2590
2590
  }
2591
2591
  !this.apiEventQueueSubject$.observed && this.apiEventQueueSubject$.pipe(groupBy(({
2592
2592
  event
2593
- }) => event), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultAPIdebounceTimeMS))), filter(() => this.apiSubject$ && !this.apiSubject$.closed)).subscribe(payload => {
2593
+ }) => event), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultAPIdebounceTimeMS))), filter(() => this.apiEventQueueSubject$ && !this.apiEventQueueSubject$.closed)).subscribe(payload => {
2594
2594
  this.apiRequest(payload);
2595
2595
  });
2596
2596
  }
@@ -2731,12 +2731,9 @@ class FormField {
2731
2731
  * sets valid field state and notifies form instance via formValidNotification$
2732
2732
  */
2733
2733
  set valid(valid) {
2734
- if (this._valid !== valid) {
2735
- this._valid = valid;
2736
- this.formValidNotification$.next({
2737
- fieldTrigger: this.name
2738
- });
2739
- }
2734
+ if (typeof valid !== 'boolean' && this.valid === valid) return;
2735
+ this._valid = valid;
2736
+ this.triggerFieldValidNotification();
2740
2737
  }
2741
2738
  /**
2742
2739
  * Retrieves the validity status of the form field.
@@ -2746,6 +2743,18 @@ class FormField {
2746
2743
  get valid() {
2747
2744
  return this._valid;
2748
2745
  }
2746
+ /**
2747
+ * triggers field valid notification to handle the form instance valid notification
2748
+ *
2749
+ * Note: since form unmount can occur before field unmount, this subject might already be closed by form instance
2750
+ * quick workaround is to check if the subject is already closed before emitting
2751
+ * if form instance onValid or template form.valid doesn't work properly, might be due to this workaround
2752
+ */
2753
+ triggerFieldValidNotification() {
2754
+ !this.fieldValidNotification$.closed && this.fieldValidNotification$.next({
2755
+ fieldTrigger: this.name
2756
+ });
2757
+ }
2749
2758
  /**
2750
2759
  * Retrieves the error messages associated with the form field.
2751
2760
  *
@@ -2791,13 +2800,12 @@ class FormField {
2791
2800
  * @param {TApiResponse} response - The new API response data to be set.
2792
2801
  */
2793
2802
  set api(response) {
2794
- if (typeof response === 'undefined' || isEqual(response, this.api)) return;
2803
+ if (typeof response === 'undefined') return;
2795
2804
  this._api = response;
2796
- this.apiSubject$.next(this.api);
2797
2805
  this.templateSubject$.next({
2798
2806
  scope: 'fields',
2799
2807
  key: this.name,
2800
- event: 'ON_API'
2808
+ event: 'ON_API_RESPONSE'
2801
2809
  });
2802
2810
  // this.apiResponseSubject$.next({ key: this.name });
2803
2811
  this.emitEvents({
@@ -2805,7 +2813,20 @@ class FormField {
2805
2813
  });
2806
2814
  }
2807
2815
  /**
2808
- * Retrieves the mounted status of the field.
2816
+ * notifies templates and event binded field configurations that a request starts it's processing
2817
+ */
2818
+ notifyApiRequest() {
2819
+ this._api.apiState.loading = true;
2820
+ this.templateSubject$.next({
2821
+ scope: 'fields',
2822
+ key: this.name,
2823
+ event: 'ON_API_REQUEST'
2824
+ });
2825
+ this.emitEvents({
2826
+ event: 'ON_API_FIELD_REQUEST'
2827
+ });
2828
+ }
2829
+ /** Retrieves the mounted status of the field.
2809
2830
  *
2810
2831
  * @returns {boolean} - the mounted status of the field.
2811
2832
  */
@@ -3001,6 +3022,7 @@ class FormField {
3001
3022
  }) {
3002
3023
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
3003
3024
  return __awaiter(this, void 0, void 0, function* () {
3025
+ let requestMadeOnce = false;
3004
3026
  const configRequest = config => __awaiter(this, void 0, void 0, function* () {
3005
3027
  var _k;
3006
3028
  try {
@@ -3026,20 +3048,23 @@ class FormField {
3026
3048
  };
3027
3049
  }
3028
3050
  });
3029
- if (!((_b = (_a = this.apiSchema) === null || _a === void 0 ? void 0 : _a.defaultConfig) === null || _b === void 0 ? void 0 : _b.events.includes(event)) && !(((_c = this.apiSchema) === null || _c === void 0 ? void 0 : _c.configs) && Object.keys((_d = this.apiSchema) === null || _d === void 0 ? void 0 : _d.configs).some(key => {
3051
+ if (this.api.apiState.lastEvent === 'ON_API_FIELD_RESPONSE' && event === 'ON_API_FIELD_RESPONSE' || !((_b = (_a = this.apiSchema) === null || _a === void 0 ? void 0 : _a.defaultConfig) === null || _b === void 0 ? void 0 : _b.events.includes(event)) && !(((_c = this.apiSchema) === null || _c === void 0 ? void 0 : _c.configs) && Object.keys((_d = this.apiSchema) === null || _d === void 0 ? void 0 : _d.configs).some(key => {
3030
3052
  var _a, _b;
3031
3053
  return (_b = (_a = this.apiSchema) === null || _a === void 0 ? void 0 : _a.configs) === null || _b === void 0 ? void 0 : _b[key].events.includes(event);
3032
3054
  }))) return;
3033
3055
  const responses = {
3034
3056
  default: Object.assign({}, this.api.default),
3035
- named: Object.assign({}, this.api.named)
3057
+ named: Object.assign({}, this.api.named),
3058
+ apiState: Object.assign({}, this.api.apiState)
3036
3059
  };
3037
3060
  const config = (_e = this.apiSchema.defaultConfig) === null || _e === void 0 ? void 0 : _e.config;
3038
3061
  if (config && ((_g = (_f = this.apiSchema) === null || _f === void 0 ? void 0 : _f.defaultConfig) === null || _g === void 0 ? void 0 : _g.events.includes(event)) && this.checkApiRequestValidations(config)) {
3062
+ !requestMadeOnce && this.notifyApiRequest();
3039
3063
  const {
3040
3064
  response,
3041
3065
  status
3042
3066
  } = yield configRequest(config);
3067
+ requestMadeOnce = true;
3043
3068
  responses.default = {
3044
3069
  response,
3045
3070
  status
@@ -3057,10 +3082,12 @@ class FormField {
3057
3082
  var _l, _m, _o, _p;
3058
3083
  const config = (_m = (_l = this.apiSchema) === null || _l === void 0 ? void 0 : _l.configs) === null || _m === void 0 ? void 0 : _m[configKey].config;
3059
3084
  if (config && ((_p = (_o = this.apiSchema) === null || _o === void 0 ? void 0 : _o.configs) === null || _p === void 0 ? void 0 : _p[configKey].events.includes(event)) && this.checkApiRequestValidations(config)) {
3085
+ !requestMadeOnce && this.notifyApiRequest();
3060
3086
  const {
3061
3087
  response,
3062
3088
  status
3063
3089
  } = yield configRequest(config);
3090
+ requestMadeOnce = true;
3064
3091
  return {
3065
3092
  name: configKey,
3066
3093
  result: {
@@ -3076,7 +3103,11 @@ class FormField {
3076
3103
  });
3077
3104
  }
3078
3105
  }
3079
- this.api = responses;
3106
+ if (requestMadeOnce) {
3107
+ responses.apiState.lastEvent = event;
3108
+ responses.apiState.loading = false;
3109
+ this.api = responses;
3110
+ }
3080
3111
  });
3081
3112
  }
3082
3113
  /**
@@ -3091,11 +3122,8 @@ class FormField {
3091
3122
  this.fieldStateSubscription$.unsubscribe();
3092
3123
  this.propsSubject$.unsubscribe();
3093
3124
  this.errorSubject$.unsubscribe();
3094
- this.apiSubject$.unsubscribe();
3095
3125
  this.apiEventQueueSubject$.unsubscribe();
3096
- !this.formValidNotification$.closed && this.formValidNotification$.next({
3097
- fieldTrigger: this.name
3098
- });
3126
+ this.triggerFieldValidNotification();
3099
3127
  }
3100
3128
  /**
3101
3129
  * Subscribes to changes in the field state and executes the provided callback function.
@@ -3151,6 +3179,8 @@ class FormCore {
3151
3179
  this.queuedFieldResetValuesEvents = new Map();
3152
3180
  this.queuedFieldResetPropertyEvents = new Map();
3153
3181
  this.queuedInitialValues = new Map();
3182
+ this._valid = false;
3183
+ this.index = entry.index;
3154
3184
  this.schema = entry.schema;
3155
3185
  this.fields = new Map();
3156
3186
  this.action = entry.action || ((_a = entry.schema) === null || _a === void 0 ? void 0 : _a.action);
@@ -3169,9 +3199,13 @@ class FormCore {
3169
3199
  this.fieldEventSubject$ = new Subject();
3170
3200
  this.dataSubject$ = new Subject();
3171
3201
  this.mountSubject$ = new Subject();
3202
+ this.fieldValidNotification$ = new Subject();
3172
3203
  this.formValidNotification$ = new Subject();
3173
3204
  this.subscribedTemplates = [];
3174
3205
  this.templateSubscription$ = this.templateSubject$.subscribe(this.refreshTemplates.bind(this));
3206
+ this.fieldValidNotification$.subscribe(() => {
3207
+ this.validateForm();
3208
+ });
3175
3209
  this.mountSubject$.subscribe(this.mountActions.bind(this));
3176
3210
  this.initialValues = entry.initialValues || ((_j = entry.schema) === null || _j === void 0 ? void 0 : _j.initialValues);
3177
3211
  this.iVars = entry.iVars || ((_k = entry.schema) === null || _k === void 0 ? void 0 : _k.iVars) || {};
@@ -3273,16 +3307,30 @@ class FormCore {
3273
3307
  });
3274
3308
  }
3275
3309
  /**
3276
- * Checks if the form is valid by validating all form fields.
3310
+ * Validates all form fields and sets the form valid flag
3277
3311
  *
3278
- * @returns {boolean} True if the form is valid; otherwise, false.
3279
3312
  */
3280
- get isValid() {
3281
- if (this.fields.size === 0) return false;
3313
+ validateForm() {
3314
+ if (this.fields.size === 0) return this.valid = false;
3282
3315
  for (const [, field] of this.fields) {
3283
- if (!field.valid) return false;
3316
+ if (!field.valid) return this.valid = false;
3284
3317
  }
3285
- return true;
3318
+ return this.valid = true;
3319
+ }
3320
+ get valid() {
3321
+ return this._valid;
3322
+ }
3323
+ set valid(valid) {
3324
+ if (this._valid === valid) return;
3325
+ this._valid = valid;
3326
+ this.templateSubject$.next({
3327
+ event: 'ON_FORM',
3328
+ scope: 'form'
3329
+ });
3330
+ this.formValidNotification$.next({
3331
+ formIndex: this.index,
3332
+ valid: this.valid
3333
+ });
3286
3334
  }
3287
3335
  /**
3288
3336
  * Subscribes to templates for dynamic updates.
@@ -3335,6 +3383,11 @@ class FormCore {
3335
3383
  const value = get(this.iVars, [key, ...(property ? [property] : []), ...path]);
3336
3384
  return value;
3337
3385
  }
3386
+ case 'form':
3387
+ {
3388
+ const value = get(this, [key, ...(property ? [property] : []), ...path]);
3389
+ return value;
3390
+ }
3338
3391
  case 'fields':
3339
3392
  {
3340
3393
  const field = this.fields.get(key);
@@ -3833,7 +3886,7 @@ class FormCore {
3833
3886
  templateSubject$: this.templateSubject$,
3834
3887
  fieldEventSubject$: this.fieldEventSubject$,
3835
3888
  dataSubject$: this.dataSubject$,
3836
- formValidNotification$: this.formValidNotification$,
3889
+ fieldValidNotification$: this.fieldValidNotification$,
3837
3890
  mountSubject$: this.mountSubject$,
3838
3891
  config: this.config,
3839
3892
  submitEvent: this.submit.bind(this),
@@ -3888,7 +3941,7 @@ class FormCore {
3888
3941
  templateSubject$: this.templateSubject$,
3889
3942
  fieldEventSubject$: this.fieldEventSubject$,
3890
3943
  dataSubject$: this.dataSubject$,
3891
- formValidNotification$: this.formValidNotification$,
3944
+ fieldValidNotification$: this.fieldValidNotification$,
3892
3945
  mountSubject$: this.mountSubject$,
3893
3946
  config: this.config,
3894
3947
  getFormValues: this.getFormValues.bind(this),
@@ -3988,7 +4041,7 @@ class FormCore {
3988
4041
  values,
3989
4042
  metadata,
3990
4043
  erroredFields,
3991
- isValid: this.isValid
4044
+ isValid: this.valid
3992
4045
  };
3993
4046
  }
3994
4047
  /**
@@ -4049,11 +4102,9 @@ class FormCore {
4049
4102
  * @param {(payload: TFormValidationPayload) => void} callback callback function to call onValid
4050
4103
  */
4051
4104
  subscribeFormValidation(callback) {
4052
- const sub = this.formValidNotification$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS), map(({
4053
- fieldTrigger
4054
- }) => ({
4055
- fieldTrigger,
4056
- valid: this.isValid
4105
+ const sub = this.formValidNotification$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS), map(() => ({
4106
+ formIndex: this.index,
4107
+ valid: this.valid
4057
4108
  })), distinctUntilKeyChanged('valid')).subscribe({
4058
4109
  next: callback
4059
4110
  });
@@ -4068,7 +4119,7 @@ class FormCore {
4068
4119
  event: 'ON_FIELD_VALIDATION'
4069
4120
  });
4070
4121
  });
4071
- if (!this.isValid) return;
4122
+ if (!this.valid) return;
4072
4123
  const values = this.getFormValues();
4073
4124
  this.submitSubject$.next(values);
4074
4125
  }
@@ -4081,6 +4132,7 @@ class FormCore {
4081
4132
  this.fieldEventSubject$.unsubscribe();
4082
4133
  this.dataSubject$.unsubscribe();
4083
4134
  this.formValidNotification$.unsubscribe();
4135
+ this.fieldValidNotification$.unsubscribe();
4084
4136
  this.fields.forEach(field => field.destroyField());
4085
4137
  }
4086
4138
  }
@@ -4297,11 +4349,11 @@ class FormGroup {
4297
4349
  }) {
4298
4350
  const subs = ids.reduce((acc, formId) => {
4299
4351
  var _a;
4300
- const sub = (_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.formValidNotification$.pipe(groupBy(payload => `${formId}.${payload.fieldTrigger}`), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS))), startWith({
4352
+ const sub = (_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.formValidNotification$.pipe(groupBy(payload => `${formId}.${payload.formIndex}`), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS))), startWith({
4301
4353
  fieldTrigger: null
4302
4354
  }), map(() => {
4303
4355
  var _a;
4304
- return ((_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.isValid) === false ? false : true;
4356
+ return ((_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.valid) === false ? false : true;
4305
4357
  }), distinctUntilChanged());
4306
4358
  if (sub) {
4307
4359
  acc[formId] = sub;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolttech/form-engine-core",
3
- "version": "1.0.0-beta.11",
3
+ "version": "1.0.0-beta.13",
4
4
  "module": "./index.esm.js",
5
5
  "type": "module",
6
6
  "main": "./index.esm.js",
@@ -4,7 +4,7 @@ declare const TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR: RegExp;
4
4
  declare const TEMPLATE_REGEX_DELIMITATOR: RegExp;
5
5
  declare const TEMPLATE_REGEX_OPERATOR_SPLITTER: RegExp;
6
6
  declare const TEMPLATE_REGEX_OPERATOR_MATCHER: RegExp;
7
- declare const TEMPLATE_AVALIABLE_SCOPES: readonly ["fields", "iVars"];
7
+ declare const TEMPLATE_AVALIABLE_SCOPES: readonly ["fields", "iVars", "form"];
8
8
  declare const ALLOWED_RESET_PROPS_MUTATIONS: ("api" | "apiSchema" | "props" | "validations" | "visibilityConditions" | "resetValues")[];
9
9
  declare const DEFAULT_LOG_VERBOSE = false;
10
10
  export { DEFAULT_API_DEBOUNCE_TIME, DEFAULT_STATE_REFRESH_TIME, DEFAULT_LOG_VERBOSE, TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR, TEMPLATE_REGEX_DELIMITATOR, TEMPLATE_REGEX_OPERATOR_SPLITTER, TEMPLATE_REGEX_OPERATOR_MATCHER, TEMPLATE_AVALIABLE_SCOPES, ALLOWED_RESET_PROPS_MUTATIONS, };
@@ -2,7 +2,7 @@ import { Subject, Subscription } from 'rxjs';
2
2
  import { TApiConfig, TApiEvent, TApiResponse, TErrorMessages, TFormatters, TMasks, TResetPathMethods, TResetValueMethods, TSchemaFormConfig, TValidations, TVisibility } from '../types/schema';
3
3
  import { IComponentSchema, IComponentSchemaAsFormField } from '../interfaces/schema';
4
4
  import { IState } from '../interfaces/state';
5
- import { TEvents, TFieldEvent, TFormValidationPayload, TValueChangeEvent } from '../types/event';
5
+ import { TEvents, TFieldEvent, TFieldValidationPayload, TValueChangeEvent } from '../types/event';
6
6
  import { TMapper } from '../types/mapper';
7
7
  import { SafeSubject } from '../helpers/SafeSubject';
8
8
  import { TTemplateEvent } from '../types/template';
@@ -44,7 +44,6 @@ declare class FormField {
44
44
  valueSubject$: SafeSubject<Record<string, unknown>>;
45
45
  valueSubscription$: Subscription;
46
46
  visibilitySubject$: SafeSubject<boolean>;
47
- apiSubject$: SafeSubject<TApiResponse>;
48
47
  fieldEventSubject$: Subject<TFieldEvent>;
49
48
  apiEventQueueSubject$: SafeSubject<{
50
49
  event: TEvents;
@@ -55,7 +54,7 @@ declare class FormField {
55
54
  key: string;
56
55
  event: TEvents;
57
56
  }>;
58
- formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
57
+ fieldValidNotification$: Subject<TFieldValidationPayload>;
59
58
  mountSubject$: Subject<{
60
59
  key: string;
61
60
  status: boolean;
@@ -93,7 +92,7 @@ declare class FormField {
93
92
  * @param {TMapper<unknown>} options.mapper, - component generic mapper containing render parameters for adapters
94
93
  * @param {() => TFormValues<unknown>} options.getFormValues, - form instance function that builds onData parameter payload from fields
95
94
  */
96
- constructor({ schemaComponent, config, path, children, validateVisibility, resetValue, resetProperty, templateSubject$, fieldEventSubject$, dataSubject$, formValidNotification$, mountSubject$, mapper, getFormValues, submitEvent, visibility, }: {
95
+ constructor({ schemaComponent, config, path, children, validateVisibility, resetValue, resetProperty, templateSubject$, fieldEventSubject$, dataSubject$, fieldValidNotification$, mountSubject$, mapper, getFormValues, submitEvent, visibility, }: {
97
96
  schemaComponent: IComponentSchema;
98
97
  config?: TSchemaFormConfig;
99
98
  path?: string;
@@ -117,7 +116,7 @@ declare class FormField {
117
116
  key: string;
118
117
  event: TEvents;
119
118
  }>;
120
- formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
119
+ fieldValidNotification$: Subject<TFieldValidationPayload>;
121
120
  mountSubject$: Subject<{
122
121
  key: string;
123
122
  status: boolean;
@@ -192,6 +191,14 @@ declare class FormField {
192
191
  * @returns {boolean} - The validity status of the form field.
193
192
  */
194
193
  get valid(): boolean;
194
+ /**
195
+ * triggers field valid notification to handle the form instance valid notification
196
+ *
197
+ * Note: since form unmount can occur before field unmount, this subject might already be closed by form instance
198
+ * quick workaround is to check if the subject is already closed before emitting
199
+ * if form instance onValid or template form.valid doesn't work properly, might be due to this workaround
200
+ */
201
+ triggerFieldValidNotification(): void;
195
202
  /**
196
203
  * Retrieves the error messages associated with the form field.
197
204
  *
@@ -217,7 +224,10 @@ declare class FormField {
217
224
  */
218
225
  set api(response: TApiResponse);
219
226
  /**
220
- * Retrieves the mounted status of the field.
227
+ * notifies templates and event binded field configurations that a request starts it's processing
228
+ */
229
+ notifyApiRequest(): void;
230
+ /** Retrieves the mounted status of the field.
221
231
  *
222
232
  * @returns {boolean} - the mounted status of the field.
223
233
  */
@@ -3,7 +3,7 @@ import { Subject, Subscription } from 'rxjs';
3
3
  import { IComponentSchema, IComponentSchemaAsFormField, IFormSchema } from '../interfaces/schema';
4
4
  import { TSchemaFormConfig } from '../types/schema';
5
5
  import { TSubscribedTemplates, TTemplateEvent } from '../types/template';
6
- import { TEvents, TFieldEvent, TFormValidationPayload, TMutationEvents } from '../types/event';
6
+ import { TEvents, TFieldEvent, TFieldValidationPayload, TFormValidationPayload, TMutationEvents } from '../types/event';
7
7
  import { TFormEntry, TFormValues } from '../types/form';
8
8
  import { TMapper } from '../types/mapper';
9
9
  import { TEMPLATE_AVALIABLE_SCOPES } from '../constants/constants';
@@ -11,6 +11,7 @@ import { TEMPLATE_AVALIABLE_SCOPES } from '../constants/constants';
11
11
  * Represents the core logic for managing a form, including field management, validation, and submission.
12
12
  */
13
13
  declare class FormCore {
14
+ index: string;
14
15
  schema?: IFormSchema;
15
16
  fields: Map<string, IFormField>;
16
17
  private _iVars;
@@ -26,7 +27,8 @@ declare class FormCore {
26
27
  key: string;
27
28
  event: TEvents;
28
29
  }>;
29
- formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
30
+ formValidNotification$: Subject<TFormValidationPayload>;
31
+ fieldValidNotification$: Subject<TFieldValidationPayload>;
30
32
  subscribedTemplates: TSubscribedTemplates[];
31
33
  action?: string;
32
34
  method?: string;
@@ -45,6 +47,7 @@ declare class FormCore {
45
47
  value: unknown;
46
48
  }>;
47
49
  queuedInitialValues: Map<string, unknown>;
50
+ _valid: boolean;
48
51
  /**
49
52
  * Creates an instance of FormCore.
50
53
  *
@@ -92,11 +95,12 @@ declare class FormCore {
92
95
  */
93
96
  set iVars(payload: Record<string, unknown>);
94
97
  /**
95
- * Checks if the form is valid by validating all form fields.
98
+ * Validates all form fields and sets the form valid flag
96
99
  *
97
- * @returns {boolean} True if the form is valid; otherwise, false.
98
100
  */
99
- get isValid(): boolean;
101
+ validateForm(): boolean;
102
+ get valid(): boolean;
103
+ set valid(valid: boolean);
100
104
  /**
101
105
  * Subscribes to templates for dynamic updates.
102
106
  */
@@ -330,7 +334,10 @@ declare class FormCore {
330
334
  *
331
335
  * @param {(payload: TFormValidationPayload) => void} callback callback function to call onValid
332
336
  */
333
- subscribeFormValidation(callback: (payload: TFormValidationPayload) => void): Subscription;
337
+ subscribeFormValidation(callback: (payload: {
338
+ formIndex: string;
339
+ valid: boolean;
340
+ }) => void): Subscription;
334
341
  /**
335
342
  * Submits the form by triggering form field events and invoking the onSubmit callback.
336
343
  */
@@ -9,7 +9,7 @@ import { TFormValues } from './form';
9
9
  * const event: TEvents = 'ON_FIELD_CHANGE';
10
10
  * ```
11
11
  */
12
- type TEvents = 'ON_FIELD_MOUNT' | 'ON_FIELD_CHANGE' | 'ON_FIELD_BLUR' | 'ON_FIELD_FOCUS' | 'ON_FIELD_CLICK' | 'ON_FIELD_KEYUP' | 'ON_FIELD_KEYDOWN' | 'ON_FIELD_CLEARED' | 'ON_FORM_SUBMIT' | 'ON_FIELD_VALIDATION' | 'ON_FORM_MOUNT' | 'ON_API_FIELD_RESPONSE';
12
+ type TEvents = 'ON_FIELD_MOUNT' | 'ON_FIELD_CHANGE' | 'ON_FIELD_BLUR' | 'ON_FIELD_FOCUS' | 'ON_FIELD_CLICK' | 'ON_FIELD_KEYUP' | 'ON_FIELD_KEYDOWN' | 'ON_FIELD_CLEARED' | 'ON_FORM_SUBMIT' | 'ON_FIELD_VALIDATION' | 'ON_FORM_MOUNT' | 'ON_API_FIELD_REQUEST' | 'ON_API_FIELD_RESPONSE';
13
13
  /**
14
14
  * @type TMutationEvents
15
15
  * Represents the different types of events that can occur internally that triggers templating.
@@ -19,7 +19,7 @@ type TEvents = 'ON_FIELD_MOUNT' | 'ON_FIELD_CHANGE' | 'ON_FIELD_BLUR' | 'ON_FIEL
19
19
  * const event: TMutationEvents = 'ON_VALUE';
20
20
  * ```
21
21
  */
22
- type TMutationEvents = 'ON_VALUE' | 'ON_PROPS' | 'ON_VISIBILITY' | 'ON_API' | 'ON_IVARS' | 'ON_FIELDS' | 'ON_RESET';
22
+ type TMutationEvents = 'ON_VALUE' | 'ON_PROPS' | 'ON_VISIBILITY' | 'ON_API_REQUEST' | 'ON_API_RESPONSE' | 'ON_IVARS' | 'ON_FIELDS' | 'ON_RESET' | 'ON_FORM';
23
23
  declare enum TMutationEnum {
24
24
  ON_VALUE = "value",
25
25
  ON_PROPS = "props",
@@ -56,9 +56,16 @@ type TFieldEvent = {
56
56
  * Form onValid event emmited payload on callback function parameter
57
57
  */
58
58
  type TFormValidationPayload = {
59
- fieldTrigger: string;
59
+ formIndex: string;
60
60
  valid: boolean;
61
61
  };
62
+ /**
63
+ * @type TFieldValidationPayload
64
+ * field event emmited payload on field validation
65
+ */
66
+ type TFieldValidationPayload = {
67
+ fieldTrigger: string;
68
+ };
62
69
  /**
63
70
  * @type TFormGroupOnDataEventPayload
64
71
  * Form Group onData event emitted payload on callback function parameter
@@ -81,4 +88,4 @@ type TFormGroupOnValidEventPayload = {
81
88
  * Form Group onSubmit event emitted payload on callback function parameter
82
89
  */
83
90
  type TFormGroupOnSubmitEventPayload<T> = Record<string, TFormValues<T> | undefined>;
84
- export { TEvents, TMutationEvents, TMutationEnum, TValueChangeEvent, TFieldEvent, TFormGroupOnDataEventPayload, TFormGroupOnValidEventPayload, TFormGroupOnSubmitEventPayload, TFormValidationPayload, };
91
+ export { TEvents, TMutationEvents, TMutationEnum, TValueChangeEvent, TFieldEvent, TFormGroupOnDataEventPayload, TFormGroupOnValidEventPayload, TFormGroupOnSubmitEventPayload, TFormValidationPayload, TFieldValidationPayload, };
@@ -667,7 +667,7 @@ type TResetValueMethods = Omit<TVisibility, 'showOnlyIfTrue' | 'validations'> &
667
667
  validations?: TSchemaValidation;
668
668
  };
669
669
  type TResetPathMethods = {
670
- property: typeof ALLOWED_RESET_PROPS_MUTATIONS[number];
670
+ property: (typeof ALLOWED_RESET_PROPS_MUTATIONS)[number];
671
671
  path: string;
672
672
  field: string;
673
673
  resettledValue: unknown;
@@ -816,6 +816,10 @@ type TApiResponsePayload = {
816
816
  type TApiResponse = {
817
817
  default: TApiResponsePayload;
818
818
  named?: Record<string, TApiResponsePayload>;
819
+ apiState: {
820
+ loading: boolean;
821
+ lastEvent?: TEvents;
822
+ };
819
823
  };
820
824
  /**
821
825
  * Represents the schema config structure