@yourself.create/ngx-form-designer 0.0.13 → 0.0.14

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.
@@ -4571,6 +4571,10 @@ class FormEventRunner {
4571
4571
  this.handleSetValue(action, evt, fields);
4572
4572
  return false;
4573
4573
  }
4574
+ if (action.type === 'clearFields') {
4575
+ this.handleClearFields(action, fields);
4576
+ return false;
4577
+ }
4574
4578
  if (action.type === 'navigate') {
4575
4579
  return this.handleNavigateAction(action, fields);
4576
4580
  }
@@ -4579,9 +4583,6 @@ class FormEventRunner {
4579
4583
  }
4580
4584
  handleSetValue(action, evt, fields) {
4581
4585
  const target = fields.find(f => f.id === action.targetFieldId);
4582
- if (!target)
4583
- return;
4584
- const previousValue = this.engine.getValue(target.name);
4585
4586
  let val;
4586
4587
  if (action.valueFrom === 'literal') {
4587
4588
  val = action.valueLiteral;
@@ -4595,16 +4596,31 @@ class FormEventRunner {
4595
4596
  val = this.engine.getValue(source.name);
4596
4597
  }
4597
4598
  }
4598
- this.engine.setValue(target.name, val);
4599
- if (!Object.is(previousValue, val)) {
4600
- this.engine.emitUiEvent({
4601
- fieldId: target.id,
4602
- fieldName: target.name,
4603
- type: 'change',
4604
- value: val
4605
- });
4599
+ this.applyFieldValue(target, val);
4600
+ }
4601
+ handleClearFields(action, fields) {
4602
+ const targetFieldIds = [...new Set(action.targetFieldIds ?? [])];
4603
+ for (const targetFieldId of targetFieldIds) {
4604
+ const target = fields.find(field => field.id === targetFieldId);
4605
+ this.applyFieldValue(target, null);
4606
4606
  }
4607
4607
  }
4608
+ applyFieldValue(target, value) {
4609
+ if (!target) {
4610
+ return;
4611
+ }
4612
+ const previousValue = this.engine.getValue(target.name);
4613
+ this.engine.setValue(target.name, value);
4614
+ if (Object.is(previousValue, value)) {
4615
+ return;
4616
+ }
4617
+ this.engine.emitUiEvent({
4618
+ fieldId: target.id,
4619
+ fieldName: target.name,
4620
+ type: 'change',
4621
+ value
4622
+ });
4623
+ }
4608
4624
  async handleApiAction(action, eventId, evt, fields) {
4609
4625
  if (!this.apiExecutor) {
4610
4626
  this.logger.warn('API action skipped because no apiExecutor was provided.', { event: evt, action });
@@ -23875,6 +23891,7 @@ class EventsWorkspaceComponent {
23875
23891
  actionTypeOptions(binding, actionIndex) {
23876
23892
  return [
23877
23893
  { label: 'Set Value', value: 'setValue' },
23894
+ { label: 'Clear Fields', value: 'clearFields' },
23878
23895
  { label: 'Log', value: 'log' },
23879
23896
  { label: 'Navigate', value: 'navigate' },
23880
23897
  { label: 'API', value: 'api', disabled: !this.canSelectApiAction(binding, actionIndex) }
@@ -23948,6 +23965,15 @@ class EventsWorkspaceComponent {
23948
23965
  binding.actions[actionIndex] = nextAction;
23949
23966
  return;
23950
23967
  }
23968
+ if (currentAction.type === 'clearFields') {
23969
+ const nextAction = {
23970
+ ...currentAction,
23971
+ ...patch,
23972
+ targetFieldIds: [...patch.targetFieldIds ?? currentAction.targetFieldIds]
23973
+ };
23974
+ binding.actions[actionIndex] = nextAction;
23975
+ return;
23976
+ }
23951
23977
  if (currentAction.type === 'log') {
23952
23978
  const nextAction = {
23953
23979
  ...currentAction,
@@ -24163,6 +24189,9 @@ class EventsWorkspaceComponent {
24163
24189
  asSetValue(action) {
24164
24190
  return action;
24165
24191
  }
24192
+ asClearFields(action) {
24193
+ return action;
24194
+ }
24166
24195
  asLog(action) {
24167
24196
  return action;
24168
24197
  }
@@ -24269,6 +24298,22 @@ class EventsWorkspaceComponent {
24269
24298
  hasApiAction(binding) {
24270
24299
  return binding.actions.some(action => action.type === 'api');
24271
24300
  }
24301
+ isClearFieldSelected(action, fieldId) {
24302
+ return action.targetFieldIds.includes(fieldId);
24303
+ }
24304
+ toggleClearFieldTarget(action, fieldId, selected) {
24305
+ if (action.type !== 'clearFields') {
24306
+ return;
24307
+ }
24308
+ const targetFieldIds = selected
24309
+ ? [...new Set([...action.targetFieldIds, fieldId])]
24310
+ : action.targetFieldIds.filter(id => id !== fieldId);
24311
+ const path = this.findActionPath(action);
24312
+ if (!path) {
24313
+ return;
24314
+ }
24315
+ this.patchAction(path.bindingIndex, path.actionIndex, { targetFieldIds });
24316
+ }
24272
24317
  canSelectApiAction(binding, actionIndex) {
24273
24318
  const current = binding.actions[actionIndex];
24274
24319
  if (current?.type === 'api')
@@ -24325,6 +24370,12 @@ class EventsWorkspaceComponent {
24325
24370
  valueLiteral: ''
24326
24371
  };
24327
24372
  }
24373
+ if (type === 'clearFields') {
24374
+ return {
24375
+ type: 'clearFields',
24376
+ targetFieldIds: []
24377
+ };
24378
+ }
24328
24379
  if (type === 'api') {
24329
24380
  return {
24330
24381
  type: 'api',
@@ -24864,6 +24915,32 @@ class EventsWorkspaceComponent {
24864
24915
  </div>
24865
24916
  </ng-container>
24866
24917
 
24918
+ <ng-container *ngIf="action.type === 'clearFields'">
24919
+ <div>
24920
+ <label class="mb-1 block text-[11px] font-medium text-gray-600">Fields To Clear</label>
24921
+ <div class="max-h-40 overflow-y-auto rounded-md border border-gray-200 bg-white">
24922
+ <label
24923
+ *ngFor="let targetField of availableTargetFields(); trackBy: trackFieldById"
24924
+ class="flex items-center gap-2 border-b border-gray-100 px-2 py-1.5 text-xs last:border-b-0">
24925
+ <input
24926
+ type="checkbox"
24927
+ class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
24928
+ [disabled]="readOnly()"
24929
+ [ngModel]="isClearFieldSelected(asClearFields(action), targetField.id)"
24930
+ (ngModelChange)="toggleClearFieldTarget(action, targetField.id, $event)">
24931
+ <span>{{ targetField.label }}</span>
24932
+ <span class="text-[10px] text-gray-400">({{ targetField.name }})</span>
24933
+ </label>
24934
+ <div *ngIf="!availableTargetFields().length" class="px-2 py-3 text-xs text-gray-500">
24935
+ No fields available.
24936
+ </div>
24937
+ </div>
24938
+ <p class="mt-2 text-[10px] text-gray-500">
24939
+ Clears selected fields to an empty runtime value.
24940
+ </p>
24941
+ </div>
24942
+ </ng-container>
24943
+
24867
24944
  <ng-container *ngIf="action.type === 'log'">
24868
24945
  <label class="mb-1 block text-[11px] font-medium text-gray-600">Message</label>
24869
24946
  <input
@@ -25245,6 +25322,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
25245
25322
  </div>
25246
25323
  </ng-container>
25247
25324
 
25325
+ <ng-container *ngIf="action.type === 'clearFields'">
25326
+ <div>
25327
+ <label class="mb-1 block text-[11px] font-medium text-gray-600">Fields To Clear</label>
25328
+ <div class="max-h-40 overflow-y-auto rounded-md border border-gray-200 bg-white">
25329
+ <label
25330
+ *ngFor="let targetField of availableTargetFields(); trackBy: trackFieldById"
25331
+ class="flex items-center gap-2 border-b border-gray-100 px-2 py-1.5 text-xs last:border-b-0">
25332
+ <input
25333
+ type="checkbox"
25334
+ class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
25335
+ [disabled]="readOnly()"
25336
+ [ngModel]="isClearFieldSelected(asClearFields(action), targetField.id)"
25337
+ (ngModelChange)="toggleClearFieldTarget(action, targetField.id, $event)">
25338
+ <span>{{ targetField.label }}</span>
25339
+ <span class="text-[10px] text-gray-400">({{ targetField.name }})</span>
25340
+ </label>
25341
+ <div *ngIf="!availableTargetFields().length" class="px-2 py-3 text-xs text-gray-500">
25342
+ No fields available.
25343
+ </div>
25344
+ </div>
25345
+ <p class="mt-2 text-[10px] text-gray-500">
25346
+ Clears selected fields to an empty runtime value.
25347
+ </p>
25348
+ </div>
25349
+ </ng-container>
25350
+
25248
25351
  <ng-container *ngIf="action.type === 'log'">
25249
25352
  <label class="mb-1 block text-[11px] font-medium text-gray-600">Message</label>
25250
25353
  <input
@@ -32814,11 +32917,7 @@ class TextFieldWidgetComponent {
32814
32917
  this.clearResolvedValue();
32815
32918
  return;
32816
32919
  }
32817
- this.control.setValue(val, { emitEvent: false });
32818
- this.syncFormattedNumberValue();
32819
- if (this.engine) {
32820
- this.engine.setValue(this.config.name, val);
32821
- }
32920
+ this.applyResolvedValue(val);
32822
32921
  }
32823
32922
  catch {
32824
32923
  // Ignore failed datasource refreshes; field remains editable.
@@ -32830,11 +32929,25 @@ class TextFieldWidgetComponent {
32830
32929
  }
32831
32930
  clearResolvedValue() {
32832
32931
  this.displayPrefix = '';
32833
- this.control.setValue(null, { emitEvent: false });
32932
+ this.applyResolvedValue(null);
32933
+ }
32934
+ applyResolvedValue(value) {
32935
+ const previousValue = this.engine?.getValue(this.config.name);
32936
+ this.control.setValue(value, { emitEvent: false });
32834
32937
  this.syncFormattedNumberValue();
32835
- if (this.engine) {
32836
- this.engine.setValue(this.config.name, null);
32938
+ if (!this.engine) {
32939
+ return;
32940
+ }
32941
+ this.engine.setValue(this.config.name, value);
32942
+ if (Object.is(previousValue, value)) {
32943
+ return;
32837
32944
  }
32945
+ this.engine.emitUiEvent({
32946
+ fieldId: this.config.id,
32947
+ fieldName: this.config.name,
32948
+ type: 'change',
32949
+ value
32950
+ });
32838
32951
  }
32839
32952
  async hasSelectedRowMatch() {
32840
32953
  const cfg = this.config.dataConfig;