@aemforms/af-core 0.22.99 → 0.22.100

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.
@@ -116,10 +116,12 @@ class DataValue {
116
116
  $_value;
117
117
  $_type;
118
118
  $_fields = [];
119
- constructor($_name, $_value, $_type = typeof $_value) {
119
+ parent;
120
+ constructor($_name, $_value, $_type = typeof $_value, parent) {
120
121
  this.$_name = $_name;
121
122
  this.$_value = $_value;
122
123
  this.$_type = $_type;
124
+ this.parent = parent;
123
125
  }
124
126
  valueOf() {
125
127
  return this.$_value;
@@ -156,6 +158,9 @@ class DataValue {
156
158
  get $isDataGroup() {
157
159
  return false;
158
160
  }
161
+ $addDataNode(name, value, override = false) {
162
+ throw 'add Data Node is called on a data value';
163
+ }
159
164
  }
160
165
 
161
166
  const value = Symbol('NullValue');
@@ -188,25 +193,25 @@ const NullDataValue = new NullDataValueClass();
188
193
 
189
194
  class DataGroup extends DataValue {
190
195
  $_items;
191
- createEntry(key, value) {
192
- const t = value instanceof Array ? 'array' : typeof value;
196
+ createEntry(key, value, parent) {
197
+ const t = Array.isArray(value) ? 'array' : typeof value;
193
198
  if (typeof value === 'object' && value != null) {
194
- return new DataGroup(key, value, t);
199
+ return new DataGroup(key, value, t, parent);
195
200
  }
196
201
  else {
197
- return new DataValue(key, value, t);
202
+ return new DataValue(key, value, t, parent);
198
203
  }
199
204
  }
200
- constructor(_name, _value, _type = typeof _value) {
201
- super(_name, _value, _type);
205
+ constructor(_name, _value, _type = typeof _value, parent) {
206
+ super(_name, _value, _type, parent);
202
207
  if (_value instanceof Array) {
203
208
  this.$_items = _value.map((value, index) => {
204
- return this.createEntry(index, value);
209
+ return this.createEntry(index, value, this);
205
210
  });
206
211
  }
207
212
  else {
208
213
  this.$_items = Object.fromEntries(Object.entries(_value).map(([key, value]) => {
209
- return [key, this.createEntry(key, value)];
214
+ return [key, this.createEntry(key, value, this)];
210
215
  }));
211
216
  }
212
217
  }
@@ -224,9 +229,16 @@ class DataGroup extends DataValue {
224
229
  return Object.entries(this.$_items).length;
225
230
  }
226
231
  $convertToDataValue() {
227
- return new DataValue(this.$name, this.$value, this.$type);
232
+ return new DataValue(this.$name, this.$value, this.$type, this.parent);
228
233
  }
229
- $addDataNode(name, value, override = false) {
234
+ syncDataAndFormModel(fromContainer) {
235
+ this.$_fields.forEach(x => {
236
+ if (fromContainer && fromContainer !== x) {
237
+ x.syncDataAndFormModel(this);
238
+ }
239
+ });
240
+ }
241
+ $addDataNode(name, value, override = false, fromContainer = null) {
230
242
  if (value !== NullDataValue) {
231
243
  if (this.$type === 'array') {
232
244
  const index = name;
@@ -236,15 +248,18 @@ class DataGroup extends DataValue {
236
248
  else {
237
249
  this.$_items[name] = value;
238
250
  }
251
+ this.syncDataAndFormModel(fromContainer);
239
252
  }
240
253
  else {
241
254
  this.$_items[name] = value;
242
255
  }
256
+ value.parent = this;
243
257
  }
244
258
  }
245
- $removeDataNode(name) {
259
+ $removeDataNode(name, fromContainer = null) {
246
260
  if (this.$type === 'array') {
247
261
  this.$_items.splice(name, 1);
262
+ this.syncDataAndFormModel(fromContainer);
248
263
  }
249
264
  else {
250
265
  this.$_items[name] = undefined;
@@ -1392,7 +1407,7 @@ class BaseNode {
1392
1407
  }
1393
1408
  return [];
1394
1409
  }
1395
- _bindToDataModel(contextualDataModel) {
1410
+ bindToDataModel(contextualDataModel) {
1396
1411
  if (this.fieldType === 'form' || this.id === '$form') {
1397
1412
  this._data = contextualDataModel;
1398
1413
  return;
@@ -1454,6 +1469,7 @@ class BaseNode {
1454
1469
  _data?.$bindToField(this);
1455
1470
  this._data = _data;
1456
1471
  }
1472
+ return this._data;
1457
1473
  }
1458
1474
  _data;
1459
1475
  getDataNode() {
@@ -1493,7 +1509,7 @@ class BaseNode {
1493
1509
  dataNode = parent.getDataNode();
1494
1510
  parent = parent.parent;
1495
1511
  } while (dataNode === undefined);
1496
- this._bindToDataModel(dataNode);
1512
+ this.bindToDataModel(dataNode);
1497
1513
  }
1498
1514
  }
1499
1515
  _applyUpdates(propNames, updates) {
@@ -2034,7 +2050,7 @@ class Container extends Scriptable {
2034
2050
  }
2035
2051
  const _data = retVal.defaultDataModel(instanceIndex);
2036
2052
  if (_data) {
2037
- dataNode.$addDataNode(instanceIndex, _data);
2053
+ dataNode.$addDataNode(instanceIndex, _data, false, this);
2038
2054
  }
2039
2055
  retVal._initialize('create');
2040
2056
  this.notifyDependents(propertyChange('items', retVal.getState(), null));
@@ -2059,7 +2075,7 @@ class Container extends Scriptable {
2059
2075
  if (this._children.length > this._jsonModel.minItems) {
2060
2076
  this._childrenReference.pop();
2061
2077
  this._children.splice(instanceIndex, 1);
2062
- this.getDataNode().$removeDataNode(instanceIndex);
2078
+ this.getDataNode().$removeDataNode(instanceIndex, this);
2063
2079
  for (let i = instanceIndex; i < this._children.length; i++) {
2064
2080
  this._children[i].dispatch(new ExecuteRule());
2065
2081
  }
@@ -2096,12 +2112,36 @@ class Container extends Scriptable {
2096
2112
  dispatch(action) {
2097
2113
  super.dispatch(action);
2098
2114
  }
2099
- importData(contextualDataModel) {
2100
- this._bindToDataModel(contextualDataModel);
2101
- const dataNode = this.getDataNode() || contextualDataModel;
2102
- this.syncDataAndFormModel(dataNode);
2115
+ importData(dataModel) {
2116
+ if (typeof this._data !== 'undefined' && this.type === 'array' && Array.isArray(dataModel)) {
2117
+ const dataGroup = new DataGroup(this._data.$name, dataModel, this._data.$type, this._data.parent);
2118
+ try {
2119
+ this._data.parent?.$addDataNode(dataGroup.$name, dataGroup, true);
2120
+ }
2121
+ catch (e) {
2122
+ this.form.logger.error(`unable to setItems for ${this.qualifiedName} : ${e}`);
2123
+ return;
2124
+ }
2125
+ this._data = dataGroup;
2126
+ const result = this.syncDataAndFormModel(dataGroup);
2127
+ const newLength = this.items.length;
2128
+ result.added.forEach((item) => {
2129
+ this.notifyDependents(propertyChange('items', item.getState(), null));
2130
+ item.dispatch(new Initialize());
2131
+ });
2132
+ for (let i = 0; i < newLength; i += 1) {
2133
+ this._children[i].dispatch(new ExecuteRule());
2134
+ }
2135
+ result.removed.forEach((item) => {
2136
+ this.notifyDependents(propertyChange('items', null, item.getState()));
2137
+ });
2138
+ }
2103
2139
  }
2104
2140
  syncDataAndFormModel(contextualDataModel) {
2141
+ const result = {
2142
+ added: [],
2143
+ removed: []
2144
+ };
2105
2145
  if (contextualDataModel?.$type === 'array' && this._itemTemplate != null) {
2106
2146
  const dataLength = contextualDataModel?.$value.length;
2107
2147
  const itemsLength = this._children.length;
@@ -2111,19 +2151,26 @@ class Container extends Scriptable {
2111
2151
  const items2Remove = Math.min(itemsLength - dataLength, itemsLength - minItems);
2112
2152
  while (items2Add > 0) {
2113
2153
  items2Add--;
2114
- const child = this._addChild(this._itemTemplate);
2154
+ const child = this._addChild(this._itemTemplate, this.items.length, true);
2115
2155
  child._initialize('create');
2156
+ result.added.push(child);
2116
2157
  }
2117
2158
  if (items2Remove > 0) {
2118
- this._children.splice(dataLength, items2Remove);
2119
2159
  for (let i = 0; i < items2Remove; i++) {
2120
2160
  this._childrenReference.pop();
2161
+ this._children.pop();
2121
2162
  }
2163
+ result.removed.push(...this._children);
2122
2164
  }
2123
2165
  }
2124
2166
  this._children.forEach(x => {
2125
- x.importData(contextualDataModel);
2167
+ let dataModel = x.bindToDataModel(contextualDataModel);
2168
+ if (x.isContainer && !dataModel) {
2169
+ dataModel = contextualDataModel;
2170
+ }
2171
+ x.syncDataAndFormModel(dataModel);
2126
2172
  });
2173
+ return result;
2127
2174
  }
2128
2175
  get activeChild() {
2129
2176
  return this._activeChild;
@@ -2596,8 +2643,8 @@ class FunctionRuntimeImpl {
2596
2643
  const args = [target];
2597
2644
  return FunctionRuntimeImpl.getInstance().getFunctions().validate._func.call(undefined, args, data, interpreter);
2598
2645
  },
2599
- importData: (inputData) => {
2600
- const args = [inputData];
2646
+ importData: (inputData, qualifiedName) => {
2647
+ const args = [inputData, qualifiedName];
2601
2648
  return FunctionRuntimeImpl.getInstance().getFunctions().importData._func.call(undefined, args, data, interpreter);
2602
2649
  },
2603
2650
  exportData: () => {
@@ -2737,9 +2784,19 @@ class FunctionRuntimeImpl {
2737
2784
  importData: {
2738
2785
  _func: (args, data, interpreter) => {
2739
2786
  const inputData = args[0];
2740
- if (typeof inputData === 'object' && inputData !== null) {
2787
+ const qualifiedName = args[1];
2788
+ if (typeof inputData === 'object' && inputData !== null && !qualifiedName) {
2741
2789
  interpreter.globals.form.importData(inputData);
2742
2790
  }
2791
+ else {
2792
+ const field = interpreter.globals.form.resolveQualifiedName(qualifiedName);
2793
+ if (field?.isContainer) {
2794
+ field.importData(inputData, qualifiedName);
2795
+ }
2796
+ else {
2797
+ interpreter.globals.form.logger.error('Invalid argument passed in importData. A container is expected');
2798
+ }
2799
+ }
2743
2800
  return {};
2744
2801
  },
2745
2802
  _signature: []
@@ -2962,7 +3019,7 @@ class Form extends Container {
2962
3019
  }
2963
3020
  }
2964
3021
  this._ids = IdGenerator();
2965
- this._bindToDataModel(new DataGroup('$form', {}));
3022
+ this.bindToDataModel(new DataGroup('$form', {}));
2966
3023
  this._initialize(mode);
2967
3024
  if (mode === 'create') {
2968
3025
  this.queueEvent(new FormLoad());
@@ -3002,7 +3059,7 @@ class Form extends Container {
3002
3059
  return this._jsonModel.action;
3003
3060
  }
3004
3061
  importData(dataModel) {
3005
- this._bindToDataModel(new DataGroup('$form', dataModel));
3062
+ this.bindToDataModel(new DataGroup('$form', dataModel));
3006
3063
  this.syncDataAndFormModel(this.getDataNode());
3007
3064
  this._eventQueue.runPendingQueue();
3008
3065
  }
@@ -3395,7 +3452,7 @@ class Fieldset extends Container {
3395
3452
  return super.items ? super.items : [];
3396
3453
  }
3397
3454
  get value() {
3398
- return null;
3455
+ return this.getDataNode()?.$value;
3399
3456
  }
3400
3457
  get fieldType() {
3401
3458
  return 'panel';
@@ -4099,9 +4156,7 @@ class Field extends Scriptable {
4099
4156
  }
4100
4157
  return this.valid ? [] : [new ValidationError(this.id, [this._jsonModel.errorMessage])];
4101
4158
  }
4102
- importData(contextualDataModel) {
4103
- this._bindToDataModel(contextualDataModel);
4104
- const dataNode = this.getDataNode();
4159
+ syncDataAndFormModel(dataNode) {
4105
4160
  if (dataNode !== undefined && dataNode !== NullDataValue && dataNode.$value !== this._jsonModel.value) {
4106
4161
  const changeAction = propertyChange('value', dataNode.$value, this._jsonModel.value);
4107
4162
  this._jsonModel.value = dataNode.$value;
@@ -4275,9 +4330,7 @@ class FileUpload extends Field {
4275
4330
  const filesInfo = await processFiles(val instanceof Array ? val : [val]);
4276
4331
  return filesInfo;
4277
4332
  }
4278
- importData(dataModel) {
4279
- this._bindToDataModel(dataModel);
4280
- const dataNode = this.getDataNode();
4333
+ syncDataAndFormModel(dataNode) {
4281
4334
  if (dataNode !== undefined && dataNode !== NullDataValue) {
4282
4335
  const value = dataNode?.$value;
4283
4336
  if (value != null) {
@@ -4516,7 +4569,10 @@ class FormFieldFactoryImpl {
4516
4569
  fieldType: child.fieldType,
4517
4570
  type: 'array',
4518
4571
  name: child.name,
4519
- dataRef: child.dataRef
4572
+ dataRef: child.dataRef,
4573
+ events: {
4574
+ 'custom:setProperty': '$event.payload'
4575
+ }
4520
4576
  },
4521
4577
  ...{
4522
4578
  'items': [newChild]
@@ -4590,7 +4646,7 @@ const restoreFormInstance = (formModel, data = null, { logLevel } = defaultOptio
4590
4646
  try {
4591
4647
  const form = new Form({ ...formModel }, FormFieldFactory, new RuleEngine(), new EventQueue(new Logger(logLevel)), logLevel, 'restore');
4592
4648
  if (data) {
4593
- form._bindToDataModel(new DataGroup('$form', data));
4649
+ form.bindToDataModel(new DataGroup('$form', data));
4594
4650
  form.syncDataAndFormModel(form.getDataNode());
4595
4651
  }
4596
4652
  form.getEventQueue().empty();
@@ -83,8 +83,8 @@ export declare abstract class BaseNode<T extends BaseJson> implements BaseModel
83
83
  notifyDependents(action: Action): void;
84
84
  protected isEmpty(value?: any): boolean;
85
85
  _setProperty<T>(prop: string, newValue: T, notify?: boolean, notifyChildren?: (action: Action) => void): any;
86
- _bindToDataModel(contextualDataModel: DataGroup): void;
87
- private _data?;
86
+ bindToDataModel(contextualDataModel: DataGroup): DataValue | undefined;
87
+ protected _data?: DataValue;
88
88
  getDataNode(): DataValue | undefined;
89
89
  get lang(): string | undefined;
90
90
  get properties(): {
@@ -94,7 +94,7 @@ export declare abstract class BaseNode<T extends BaseJson> implements BaseModel
94
94
  [key: string]: any;
95
95
  });
96
96
  abstract defaultDataModel(name: string | number): DataValue | undefined;
97
- abstract importData(a: DataGroup): any;
97
+ abstract syncDataAndFormModel(a?: DataValue | DataGroup): any;
98
98
  getNonTransparentParent(): ContainerModel;
99
99
  _initialize(mode?: FormCreationMode): void;
100
100
  protected _applyUpdates(propNames: string[], updates: any): any;
@@ -64,8 +64,8 @@ declare abstract class Container<T extends ContainerJson & RulesJson> extends Sc
64
64
  reset(): void;
65
65
  validate(): import("./types/Model").ValidationError[];
66
66
  dispatch(action: Action): void;
67
- importData(contextualDataModel: DataGroup): void;
68
- syncDataAndFormModel(contextualDataModel?: DataGroup): void;
67
+ importData(dataModel: any): void;
68
+ syncDataAndFormModel(contextualDataModel?: DataGroup): any;
69
69
  get activeChild(): BaseModel | null;
70
70
  set activeChild(c: BaseModel | null);
71
71
  get enabled(): boolean | undefined;
@@ -1,7 +1,6 @@
1
1
  import { Action, ConstraintsMessages, ContainerModel, FieldJson, FieldModel, FormModel, ValidationError } from './types';
2
2
  import Scriptable from './Scriptable';
3
3
  import DataValue from './data/DataValue';
4
- import DataGroup from './data/DataGroup';
5
4
  declare class Field extends Scriptable<FieldJson> implements FieldModel {
6
5
  #private;
7
6
  constructor(params: FieldJson, _options: {
@@ -152,7 +151,7 @@ declare class Field extends Scriptable<FieldJson> implements FieldModel {
152
151
  protected evaluateConstraints(): any;
153
152
  triggerValidationEvent(changes: any): void;
154
153
  validate(): ValidationError[];
155
- importData(contextualDataModel: DataGroup): void;
154
+ syncDataAndFormModel(dataNode: DataValue): void;
156
155
  defaultDataModel(name: string | number): DataValue;
157
156
  getState(isRepeatableChild?: boolean, forRestore?: boolean): {
158
157
  editFormat: string | undefined;
@@ -11,6 +11,6 @@ export declare class Fieldset extends Container<FieldsetJson> implements Fieldse
11
11
  private _applyDefaults;
12
12
  get type(): "array" | "object" | undefined;
13
13
  get items(): (import("./types/Model").FieldModel | FieldsetModel)[];
14
- get value(): null;
14
+ get value(): any;
15
15
  get fieldType(): string;
16
16
  }
@@ -1,6 +1,6 @@
1
1
  import Field from './Field';
2
2
  import { FieldModel } from './types/index';
3
- import DataGroup from './data/DataGroup';
3
+ import DataValue from './data/DataValue';
4
4
  declare class FileUpload extends Field implements FieldModel {
5
5
  protected _getDefaults(): {
6
6
  accept: string[];
@@ -22,6 +22,6 @@ declare class FileUpload extends Field implements FieldModel {
22
22
  protected getInternalType(): "file" | "file[]";
23
23
  protected getDataNodeValue(typedValue: any): any;
24
24
  serialize(): Promise<unknown[] | null>;
25
- importData(dataModel: DataGroup): void;
25
+ syncDataAndFormModel(dataNode: DataValue): void;
26
26
  }
27
27
  export default FileUpload;
@@ -1,4 +1,5 @@
1
1
  import DataValue from './DataValue';
2
+ import { ContainerModel } from '../types';
2
3
  export default class DataGroup extends DataValue {
3
4
  $_items: {
4
5
  [key: string]: DataValue | DataGroup;
@@ -6,14 +7,15 @@ export default class DataGroup extends DataValue {
6
7
  private createEntry;
7
8
  constructor(_name: string | number, _value: {
8
9
  [key: string]: any;
9
- } | any[], _type?: string);
10
+ } | any[], _type?: string, parent?: DataValue);
10
11
  get $value(): Array<any> | {
11
12
  [key: string]: any;
12
13
  };
13
14
  get $length(): number;
14
15
  $convertToDataValue(): DataValue;
15
- $addDataNode(name: string | number, value: DataGroup | DataValue, override?: boolean): void;
16
- $removeDataNode(name: string | number): void;
16
+ private syncDataAndFormModel;
17
+ $addDataNode(name: string | number, value: DataGroup | DataValue, override?: boolean, fromContainer?: ContainerModel | null): void;
18
+ $removeDataNode(name: string | number, fromContainer?: ContainerModel | null): void;
17
19
  $getDataNode(name: string | number): any;
18
20
  $containsDataNode(name: string | number): boolean;
19
21
  get $isDataGroup(): boolean;
@@ -4,7 +4,8 @@ export default class DataValue {
4
4
  private $_value;
5
5
  private $_type;
6
6
  $_fields: Array<FieldModel>;
7
- constructor($_name: string | number, $_value: any, $_type?: string);
7
+ parent?: DataValue;
8
+ constructor($_name: string | number, $_value: any, $_type?: string, parent?: DataValue);
8
9
  valueOf(): any;
9
10
  get $name(): string | number;
10
11
  get disabled(): number | false;
@@ -14,4 +15,5 @@ export default class DataValue {
14
15
  $bindToField(field: FieldModel): void;
15
16
  $convertToDataValue(): DataValue;
16
17
  get $isDataGroup(): boolean;
18
+ $addDataNode(name: string | number, value: DataValue, override?: boolean): void;
17
19
  }
@@ -4,6 +4,7 @@ import EventQueue from '../controller/EventQueue';
4
4
  import DataGroup from '../data/DataGroup';
5
5
  import { Logger } from '../controller/Logger';
6
6
  import { Version } from '../utils/Version';
7
+ import DataValue from '../data/DataValue';
7
8
  export interface ScriptableField {
8
9
  rules?: {
9
10
  [key: string]: string;
@@ -73,7 +74,8 @@ export interface BaseModel extends ConstraintsJson, WithController {
73
74
  readonly repeatable?: boolean;
74
75
  validate(): Array<ValidationError>;
75
76
  reset(): any;
76
- importData(a?: DataGroup): any;
77
+ bindToDataModel(a?: DataGroup): any;
78
+ syncDataAndFormModel(a?: DataValue | DataGroup): any;
77
79
  getRuleNode(): any;
78
80
  ruleNodeReference(): any;
79
81
  _initialize(mode?: FormCreationMode): any;
@@ -105,6 +107,7 @@ export interface ContainerModel extends BaseModel, ScriptableField {
105
107
  items: Array<FieldsetModel | FieldModel>;
106
108
  parent: ContainerModel;
107
109
  indexOf(f: FieldModel | FieldsetModel): number;
110
+ importData(data: any): any;
108
111
  isTransparent(): boolean;
109
112
  activeChild: BaseModel | null;
110
113
  }
@@ -119,7 +122,6 @@ export interface FormModel extends ContainerModel, WithState<FormJson> {
119
122
  readonly title: string;
120
123
  readonly logger: Logger;
121
124
  readonly specVersion: Version;
122
- importData(data: any): any;
123
125
  exportData(): any;
124
126
  getElement(id: string): FieldModel | FormModel | FieldsetModel;
125
127
  getUniqueId(): string;
package/lib/BaseNode.d.ts CHANGED
@@ -83,8 +83,8 @@ export declare abstract class BaseNode<T extends BaseJson> implements BaseModel
83
83
  notifyDependents(action: Action): void;
84
84
  protected isEmpty(value?: any): boolean;
85
85
  _setProperty<T>(prop: string, newValue: T, notify?: boolean, notifyChildren?: (action: Action) => void): any;
86
- _bindToDataModel(contextualDataModel: DataGroup): void;
87
- private _data?;
86
+ bindToDataModel(contextualDataModel: DataGroup): DataValue | undefined;
87
+ protected _data?: DataValue;
88
88
  getDataNode(): DataValue | undefined;
89
89
  get lang(): string | undefined;
90
90
  get properties(): {
@@ -94,7 +94,7 @@ export declare abstract class BaseNode<T extends BaseJson> implements BaseModel
94
94
  [key: string]: any;
95
95
  });
96
96
  abstract defaultDataModel(name: string | number): DataValue | undefined;
97
- abstract importData(a: DataGroup): any;
97
+ abstract syncDataAndFormModel(a?: DataValue | DataGroup): any;
98
98
  getNonTransparentParent(): ContainerModel;
99
99
  _initialize(mode?: FormCreationMode): void;
100
100
  protected _applyUpdates(propNames: string[], updates: any): any;
package/lib/BaseNode.js CHANGED
@@ -358,7 +358,7 @@ class BaseNode {
358
358
  }
359
359
  return [];
360
360
  }
361
- _bindToDataModel(contextualDataModel) {
361
+ bindToDataModel(contextualDataModel) {
362
362
  if (this.fieldType === 'form' || this.id === '$form') {
363
363
  this._data = contextualDataModel;
364
364
  return;
@@ -420,6 +420,7 @@ class BaseNode {
420
420
  _data === null || _data === void 0 ? void 0 : _data.$bindToField(this);
421
421
  this._data = _data;
422
422
  }
423
+ return this._data;
423
424
  }
424
425
  getDataNode() {
425
426
  return this._data;
@@ -458,7 +459,7 @@ class BaseNode {
458
459
  dataNode = parent.getDataNode();
459
460
  parent = parent.parent;
460
461
  } while (dataNode === undefined);
461
- this._bindToDataModel(dataNode);
462
+ this.bindToDataModel(dataNode);
462
463
  }
463
464
  }
464
465
  _applyUpdates(propNames, updates) {
@@ -64,8 +64,8 @@ declare abstract class Container<T extends ContainerJson & RulesJson> extends Sc
64
64
  reset(): void;
65
65
  validate(): import("./types/Model").ValidationError[];
66
66
  dispatch(action: Action): void;
67
- importData(contextualDataModel: DataGroup): void;
68
- syncDataAndFormModel(contextualDataModel?: DataGroup): void;
67
+ importData(dataModel: any): void;
68
+ syncDataAndFormModel(contextualDataModel?: DataGroup): any;
69
69
  get activeChild(): BaseModel | null;
70
70
  set activeChild(c: BaseModel | null);
71
71
  get enabled(): boolean | undefined;
package/lib/Container.js CHANGED
@@ -282,7 +282,7 @@ class Container extends Scriptable_1.default {
282
282
  }
283
283
  const _data = retVal.defaultDataModel(instanceIndex);
284
284
  if (_data) {
285
- dataNode.$addDataNode(instanceIndex, _data);
285
+ dataNode.$addDataNode(instanceIndex, _data, false, this);
286
286
  }
287
287
  retVal._initialize('create');
288
288
  this.notifyDependents((0, Events_1.propertyChange)('items', retVal.getState(), null));
@@ -307,7 +307,7 @@ class Container extends Scriptable_1.default {
307
307
  if (this._children.length > this._jsonModel.minItems) {
308
308
  this._childrenReference.pop();
309
309
  this._children.splice(instanceIndex, 1);
310
- this.getDataNode().$removeDataNode(instanceIndex);
310
+ this.getDataNode().$removeDataNode(instanceIndex, this);
311
311
  for (let i = instanceIndex; i < this._children.length; i++) {
312
312
  this._children[i].dispatch(new Events_1.ExecuteRule());
313
313
  }
@@ -345,12 +345,37 @@ class Container extends Scriptable_1.default {
345
345
  dispatch(action) {
346
346
  super.dispatch(action);
347
347
  }
348
- importData(contextualDataModel) {
349
- this._bindToDataModel(contextualDataModel);
350
- const dataNode = this.getDataNode() || contextualDataModel;
351
- this.syncDataAndFormModel(dataNode);
348
+ importData(dataModel) {
349
+ var _a;
350
+ if (typeof this._data !== 'undefined' && this.type === 'array' && Array.isArray(dataModel)) {
351
+ const dataGroup = new DataGroup_1.default(this._data.$name, dataModel, this._data.$type, this._data.parent);
352
+ try {
353
+ (_a = this._data.parent) === null || _a === void 0 ? void 0 : _a.$addDataNode(dataGroup.$name, dataGroup, true);
354
+ }
355
+ catch (e) {
356
+ this.form.logger.error(`unable to setItems for ${this.qualifiedName} : ${e}`);
357
+ return;
358
+ }
359
+ this._data = dataGroup;
360
+ const result = this.syncDataAndFormModel(dataGroup);
361
+ const newLength = this.items.length;
362
+ result.added.forEach((item) => {
363
+ this.notifyDependents((0, Events_1.propertyChange)('items', item.getState(), null));
364
+ item.dispatch(new Events_1.Initialize());
365
+ });
366
+ for (let i = 0; i < newLength; i += 1) {
367
+ this._children[i].dispatch(new Events_1.ExecuteRule());
368
+ }
369
+ result.removed.forEach((item) => {
370
+ this.notifyDependents((0, Events_1.propertyChange)('items', null, item.getState()));
371
+ });
372
+ }
352
373
  }
353
374
  syncDataAndFormModel(contextualDataModel) {
375
+ const result = {
376
+ added: [],
377
+ removed: []
378
+ };
354
379
  if ((contextualDataModel === null || contextualDataModel === void 0 ? void 0 : contextualDataModel.$type) === 'array' && this._itemTemplate != null) {
355
380
  const dataLength = contextualDataModel === null || contextualDataModel === void 0 ? void 0 : contextualDataModel.$value.length;
356
381
  const itemsLength = this._children.length;
@@ -360,19 +385,26 @@ class Container extends Scriptable_1.default {
360
385
  const items2Remove = Math.min(itemsLength - dataLength, itemsLength - minItems);
361
386
  while (items2Add > 0) {
362
387
  items2Add--;
363
- const child = this._addChild(this._itemTemplate);
388
+ const child = this._addChild(this._itemTemplate, this.items.length, true);
364
389
  child._initialize('create');
390
+ result.added.push(child);
365
391
  }
366
392
  if (items2Remove > 0) {
367
- this._children.splice(dataLength, items2Remove);
368
393
  for (let i = 0; i < items2Remove; i++) {
369
394
  this._childrenReference.pop();
395
+ this._children.pop();
370
396
  }
397
+ result.removed.push(...this._children);
371
398
  }
372
399
  }
373
400
  this._children.forEach(x => {
374
- x.importData(contextualDataModel);
401
+ let dataModel = x.bindToDataModel(contextualDataModel);
402
+ if (x.isContainer && !dataModel) {
403
+ dataModel = contextualDataModel;
404
+ }
405
+ x.syncDataAndFormModel(dataModel);
375
406
  });
407
+ return result;
376
408
  }
377
409
  get activeChild() {
378
410
  return this._activeChild;
package/lib/Field.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Action, ConstraintsMessages, ContainerModel, FieldJson, FieldModel, FormModel, ValidationError } from './types';
2
2
  import Scriptable from './Scriptable';
3
3
  import DataValue from './data/DataValue';
4
- import DataGroup from './data/DataGroup';
5
4
  declare class Field extends Scriptable<FieldJson> implements FieldModel {
6
5
  #private;
7
6
  constructor(params: FieldJson, _options: {
@@ -152,7 +151,7 @@ declare class Field extends Scriptable<FieldJson> implements FieldModel {
152
151
  protected evaluateConstraints(): any;
153
152
  triggerValidationEvent(changes: any): void;
154
153
  validate(): ValidationError[];
155
- importData(contextualDataModel: DataGroup): void;
154
+ syncDataAndFormModel(dataNode: DataValue): void;
156
155
  defaultDataModel(name: string | number): DataValue;
157
156
  getState(isRepeatableChild?: boolean, forRestore?: boolean): {
158
157
  editFormat: string | undefined;
package/lib/Field.js CHANGED
@@ -685,9 +685,7 @@ class Field extends Scriptable_1.default {
685
685
  }
686
686
  return this.valid ? [] : [new types_1.ValidationError(this.id, [this._jsonModel.errorMessage])];
687
687
  }
688
- importData(contextualDataModel) {
689
- this._bindToDataModel(contextualDataModel);
690
- const dataNode = this.getDataNode();
688
+ syncDataAndFormModel(dataNode) {
691
689
  if (dataNode !== undefined && dataNode !== EmptyDataValue_1.default && dataNode.$value !== this._jsonModel.value) {
692
690
  const changeAction = (0, Events_1.propertyChange)('value', dataNode.$value, this._jsonModel.value);
693
691
  this._jsonModel.value = dataNode.$value;
package/lib/Fieldset.d.ts CHANGED
@@ -11,6 +11,6 @@ export declare class Fieldset extends Container<FieldsetJson> implements Fieldse
11
11
  private _applyDefaults;
12
12
  get type(): "array" | "object" | undefined;
13
13
  get items(): (import("./types/Model").FieldModel | FieldsetModel)[];
14
- get value(): null;
14
+ get value(): any;
15
15
  get fieldType(): string;
16
16
  }
package/lib/Fieldset.js CHANGED
@@ -38,7 +38,8 @@ class Fieldset extends Container_1.default {
38
38
  return super.items ? super.items : [];
39
39
  }
40
40
  get value() {
41
- return null;
41
+ var _a;
42
+ return (_a = this.getDataNode()) === null || _a === void 0 ? void 0 : _a.$value;
42
43
  }
43
44
  get fieldType() {
44
45
  return 'panel';
@@ -1,6 +1,6 @@
1
1
  import Field from './Field';
2
2
  import { FieldModel } from './types/index';
3
- import DataGroup from './data/DataGroup';
3
+ import DataValue from './data/DataValue';
4
4
  declare class FileUpload extends Field implements FieldModel {
5
5
  protected _getDefaults(): {
6
6
  accept: string[];
@@ -22,6 +22,6 @@ declare class FileUpload extends Field implements FieldModel {
22
22
  protected getInternalType(): "file" | "file[]";
23
23
  protected getDataNodeValue(typedValue: any): any;
24
24
  serialize(): Promise<unknown[] | null>;
25
- importData(dataModel: DataGroup): void;
25
+ syncDataAndFormModel(dataNode: DataValue): void;
26
26
  }
27
27
  export default FileUpload;
package/lib/FileUpload.js CHANGED
@@ -103,9 +103,7 @@ class FileUpload extends Field_1.default {
103
103
  return filesInfo;
104
104
  });
105
105
  }
106
- importData(dataModel) {
107
- this._bindToDataModel(dataModel);
108
- const dataNode = this.getDataNode();
106
+ syncDataAndFormModel(dataNode) {
109
107
  if (dataNode !== undefined && dataNode !== EmptyDataValue_1.default) {
110
108
  const value = dataNode === null || dataNode === void 0 ? void 0 : dataNode.$value;
111
109
  if (value != null) {
package/lib/Form.js CHANGED
@@ -46,7 +46,7 @@ class Form extends Container_1.default {
46
46
  }
47
47
  }
48
48
  this._ids = (0, FormUtils_1.IdGenerator)();
49
- this._bindToDataModel(new DataGroup_1.default('$form', {}));
49
+ this.bindToDataModel(new DataGroup_1.default('$form', {}));
50
50
  this._initialize(mode);
51
51
  if (mode === 'create') {
52
52
  this.queueEvent(new Events_1.FormLoad());
@@ -84,7 +84,7 @@ class Form extends Container_1.default {
84
84
  return this._jsonModel.action;
85
85
  }
86
86
  importData(dataModel) {
87
- this._bindToDataModel(new DataGroup_1.default('$form', dataModel));
87
+ this.bindToDataModel(new DataGroup_1.default('$form', dataModel));
88
88
  this.syncDataAndFormModel(this.getDataNode());
89
89
  this._eventQueue.runPendingQueue();
90
90
  }
@@ -70,7 +70,7 @@ const restoreFormInstance = (formModel, data = null, { logLevel } = defaultOptio
70
70
  try {
71
71
  const form = new Form_1.default(Object.assign({}, formModel), FormCreationUtils_1.FormFieldFactory, new RuleEngine_1.default(), new EventQueue_1.default(new Logger_1.Logger(logLevel)), logLevel, 'restore');
72
72
  if (data) {
73
- form._bindToDataModel(new DataGroup_1.default('$form', data));
73
+ form.bindToDataModel(new DataGroup_1.default('$form', data));
74
74
  form.syncDataAndFormModel(form.getDataNode());
75
75
  }
76
76
  form.getEventQueue().empty();
@@ -1,4 +1,5 @@
1
1
  import DataValue from './DataValue';
2
+ import { ContainerModel } from '../types';
2
3
  export default class DataGroup extends DataValue {
3
4
  $_items: {
4
5
  [key: string]: DataValue | DataGroup;
@@ -6,14 +7,15 @@ export default class DataGroup extends DataValue {
6
7
  private createEntry;
7
8
  constructor(_name: string | number, _value: {
8
9
  [key: string]: any;
9
- } | any[], _type?: string);
10
+ } | any[], _type?: string, parent?: DataValue);
10
11
  get $value(): Array<any> | {
11
12
  [key: string]: any;
12
13
  };
13
14
  get $length(): number;
14
15
  $convertToDataValue(): DataValue;
15
- $addDataNode(name: string | number, value: DataGroup | DataValue, override?: boolean): void;
16
- $removeDataNode(name: string | number): void;
16
+ private syncDataAndFormModel;
17
+ $addDataNode(name: string | number, value: DataGroup | DataValue, override?: boolean, fromContainer?: ContainerModel | null): void;
18
+ $removeDataNode(name: string | number, fromContainer?: ContainerModel | null): void;
17
19
  $getDataNode(name: string | number): any;
18
20
  $containsDataNode(name: string | number): boolean;
19
21
  get $isDataGroup(): boolean;
@@ -6,26 +6,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const DataValue_1 = __importDefault(require("./DataValue"));
7
7
  const EmptyDataValue_1 = __importDefault(require("./EmptyDataValue"));
8
8
  class DataGroup extends DataValue_1.default {
9
- constructor(_name, _value, _type = typeof _value) {
10
- super(_name, _value, _type);
9
+ constructor(_name, _value, _type = typeof _value, parent) {
10
+ super(_name, _value, _type, parent);
11
11
  if (_value instanceof Array) {
12
12
  this.$_items = _value.map((value, index) => {
13
- return this.createEntry(index, value);
13
+ return this.createEntry(index, value, this);
14
14
  });
15
15
  }
16
16
  else {
17
17
  this.$_items = Object.fromEntries(Object.entries(_value).map(([key, value]) => {
18
- return [key, this.createEntry(key, value)];
18
+ return [key, this.createEntry(key, value, this)];
19
19
  }));
20
20
  }
21
21
  }
22
- createEntry(key, value) {
23
- const t = value instanceof Array ? 'array' : typeof value;
22
+ createEntry(key, value, parent) {
23
+ const t = Array.isArray(value) ? 'array' : typeof value;
24
24
  if (typeof value === 'object' && value != null) {
25
- return new DataGroup(key, value, t);
25
+ return new DataGroup(key, value, t, parent);
26
26
  }
27
27
  else {
28
- return new DataValue_1.default(key, value, t);
28
+ return new DataValue_1.default(key, value, t, parent);
29
29
  }
30
30
  }
31
31
  get $value() {
@@ -42,9 +42,16 @@ class DataGroup extends DataValue_1.default {
42
42
  return Object.entries(this.$_items).length;
43
43
  }
44
44
  $convertToDataValue() {
45
- return new DataValue_1.default(this.$name, this.$value, this.$type);
45
+ return new DataValue_1.default(this.$name, this.$value, this.$type, this.parent);
46
46
  }
47
- $addDataNode(name, value, override = false) {
47
+ syncDataAndFormModel(fromContainer) {
48
+ this.$_fields.forEach(x => {
49
+ if (fromContainer && fromContainer !== x) {
50
+ x.syncDataAndFormModel(this);
51
+ }
52
+ });
53
+ }
54
+ $addDataNode(name, value, override = false, fromContainer = null) {
48
55
  if (value !== EmptyDataValue_1.default) {
49
56
  if (this.$type === 'array') {
50
57
  const index = name;
@@ -54,15 +61,18 @@ class DataGroup extends DataValue_1.default {
54
61
  else {
55
62
  this.$_items[name] = value;
56
63
  }
64
+ this.syncDataAndFormModel(fromContainer);
57
65
  }
58
66
  else {
59
67
  this.$_items[name] = value;
60
68
  }
69
+ value.parent = this;
61
70
  }
62
71
  }
63
- $removeDataNode(name) {
72
+ $removeDataNode(name, fromContainer = null) {
64
73
  if (this.$type === 'array') {
65
74
  this.$_items.splice(name, 1);
75
+ this.syncDataAndFormModel(fromContainer);
66
76
  }
67
77
  else {
68
78
  this.$_items[name] = undefined;
@@ -4,7 +4,8 @@ export default class DataValue {
4
4
  private $_value;
5
5
  private $_type;
6
6
  $_fields: Array<FieldModel>;
7
- constructor($_name: string | number, $_value: any, $_type?: string);
7
+ parent?: DataValue;
8
+ constructor($_name: string | number, $_value: any, $_type?: string, parent?: DataValue);
8
9
  valueOf(): any;
9
10
  get $name(): string | number;
10
11
  get disabled(): number | false;
@@ -14,4 +15,5 @@ export default class DataValue {
14
15
  $bindToField(field: FieldModel): void;
15
16
  $convertToDataValue(): DataValue;
16
17
  get $isDataGroup(): boolean;
18
+ $addDataNode(name: string | number, value: DataValue, override?: boolean): void;
17
19
  }
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  class DataValue {
4
- constructor($_name, $_value, $_type = typeof $_value) {
4
+ constructor($_name, $_value, $_type = typeof $_value, parent) {
5
5
  this.$_name = $_name;
6
6
  this.$_value = $_value;
7
7
  this.$_type = $_type;
8
8
  this.$_fields = [];
9
+ this.parent = parent;
9
10
  }
10
11
  valueOf() {
11
12
  return this.$_value;
@@ -42,5 +43,8 @@ class DataValue {
42
43
  get $isDataGroup() {
43
44
  return false;
44
45
  }
46
+ $addDataNode(name, value, override = false) {
47
+ throw 'add Data Node is called on a data value';
48
+ }
45
49
  }
46
50
  exports.default = DataValue;
@@ -204,8 +204,8 @@ class FunctionRuntimeImpl {
204
204
  const args = [target];
205
205
  return FunctionRuntimeImpl.getInstance().getFunctions().validate._func.call(undefined, args, data, interpreter);
206
206
  },
207
- importData: (inputData) => {
208
- const args = [inputData];
207
+ importData: (inputData, qualifiedName) => {
208
+ const args = [inputData, qualifiedName];
209
209
  return FunctionRuntimeImpl.getInstance().getFunctions().importData._func.call(undefined, args, data, interpreter);
210
210
  },
211
211
  exportData: () => {
@@ -346,9 +346,19 @@ class FunctionRuntimeImpl {
346
346
  importData: {
347
347
  _func: (args, data, interpreter) => {
348
348
  const inputData = args[0];
349
- if (typeof inputData === 'object' && inputData !== null) {
349
+ const qualifiedName = args[1];
350
+ if (typeof inputData === 'object' && inputData !== null && !qualifiedName) {
350
351
  interpreter.globals.form.importData(inputData);
351
352
  }
353
+ else {
354
+ const field = interpreter.globals.form.resolveQualifiedName(qualifiedName);
355
+ if (field === null || field === void 0 ? void 0 : field.isContainer) {
356
+ field.importData(inputData, qualifiedName);
357
+ }
358
+ else {
359
+ interpreter.globals.form.logger.error('Invalid argument passed in importData. A container is expected');
360
+ }
361
+ }
352
362
  return {};
353
363
  },
354
364
  _signature: []
@@ -4,6 +4,7 @@ import EventQueue from '../controller/EventQueue';
4
4
  import DataGroup from '../data/DataGroup';
5
5
  import { Logger } from '../controller/Logger';
6
6
  import { Version } from '../utils/Version';
7
+ import DataValue from '../data/DataValue';
7
8
  export interface ScriptableField {
8
9
  rules?: {
9
10
  [key: string]: string;
@@ -73,7 +74,8 @@ export interface BaseModel extends ConstraintsJson, WithController {
73
74
  readonly repeatable?: boolean;
74
75
  validate(): Array<ValidationError>;
75
76
  reset(): any;
76
- importData(a?: DataGroup): any;
77
+ bindToDataModel(a?: DataGroup): any;
78
+ syncDataAndFormModel(a?: DataValue | DataGroup): any;
77
79
  getRuleNode(): any;
78
80
  ruleNodeReference(): any;
79
81
  _initialize(mode?: FormCreationMode): any;
@@ -105,6 +107,7 @@ export interface ContainerModel extends BaseModel, ScriptableField {
105
107
  items: Array<FieldsetModel | FieldModel>;
106
108
  parent: ContainerModel;
107
109
  indexOf(f: FieldModel | FieldsetModel): number;
110
+ importData(data: any): any;
108
111
  isTransparent(): boolean;
109
112
  activeChild: BaseModel | null;
110
113
  }
@@ -119,7 +122,6 @@ export interface FormModel extends ContainerModel, WithState<FormJson> {
119
122
  readonly title: string;
120
123
  readonly logger: Logger;
121
124
  readonly specVersion: Version;
122
- importData(data: any): any;
123
125
  exportData(): any;
124
126
  getElement(id: string): FieldModel | FormModel | FieldsetModel;
125
127
  getUniqueId(): string;
@@ -38,7 +38,10 @@ class FormFieldFactoryImpl {
38
38
  fieldType: child.fieldType,
39
39
  type: 'array',
40
40
  name: child.name,
41
- dataRef: child.dataRef
41
+ dataRef: child.dataRef,
42
+ events: {
43
+ 'custom:setProperty': '$event.payload'
44
+ }
42
45
  }, {
43
46
  'items': [newChild]
44
47
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aemforms/af-core",
3
- "version": "0.22.99",
3
+ "version": "0.22.100",
4
4
  "description": "Core Module for Forms Runtime",
5
5
  "author": "Adobe Systems",
6
6
  "license": "Adobe Proprietary",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@adobe/json-formula": "0.1.50",
40
- "@aemforms/af-formatters": "^0.22.99"
40
+ "@aemforms/af-formatters": "^0.22.100"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@babel/preset-env": "^7.20.2",