mobx-formkit 1.1.3 → 1.2.0
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/AGENTS.md +1 -1
- package/lib/Base.d.ts +25 -1
- package/lib/Base.d.ts.map +1 -1
- package/lib/Base.js +120 -17
- package/lib/Base.js.map +1 -1
- package/lib/Field.d.ts.map +1 -1
- package/lib/Field.js +43 -12
- package/lib/Field.js.map +1 -1
- package/lib/esm/Base.js +120 -17
- package/lib/esm/Base.js.map +1 -1
- package/lib/esm/Field.js +44 -13
- package/lib/esm/Field.js.map +1 -1
- package/package.json +1 -1
- package/src/Base.ts +158 -15
- package/src/Field.ts +49 -11
- package/umd/MobxFormkit.umd.js +163 -29
- package/umd/MobxFormkit.umd.js.map +1 -1
- package/umd/MobxFormkit.umd.min.js +1 -1
- package/umd/MobxFormkit.umd.min.js.map +1 -1
package/umd/MobxFormkit.umd.js
CHANGED
|
@@ -1095,7 +1095,7 @@
|
|
|
1095
1095
|
}
|
|
1096
1096
|
});
|
|
1097
1097
|
}
|
|
1098
|
-
initField(key, path, data, update = false) {
|
|
1098
|
+
initField(key, path, data, update = false, value) {
|
|
1099
1099
|
const initial = this.state.get("current", "props");
|
|
1100
1100
|
const struct = pathToStruct(path);
|
|
1101
1101
|
// try to get props from separated objects
|
|
@@ -1111,7 +1111,9 @@
|
|
|
1111
1111
|
return t;
|
|
1112
1112
|
};
|
|
1113
1113
|
const props = {
|
|
1114
|
-
$value:
|
|
1114
|
+
$value: value !== void 0
|
|
1115
|
+
? value
|
|
1116
|
+
: lodash.get(initial[SeparatedPropsMode.values], path),
|
|
1115
1117
|
$computed: _try(SeparatedPropsMode.computed),
|
|
1116
1118
|
$label: _try(SeparatedPropsMode.labels),
|
|
1117
1119
|
$placeholder: _try(SeparatedPropsMode.placeholders),
|
|
@@ -1272,6 +1274,17 @@
|
|
|
1272
1274
|
this.state.form.select(this.path ?? "", null, false);
|
|
1273
1275
|
const applyInputConverterOnUpdate = this.state.options.get(OptionsEnum.applyInputConverterOnUpdate, this);
|
|
1274
1276
|
if ($field != null && field !== void 0) {
|
|
1277
|
+
// an array provided for a field which is not an array container
|
|
1278
|
+
// is the field value itself (not a set of nested fields)
|
|
1279
|
+
const $rawValue = lodash.get(raw, $path);
|
|
1280
|
+
const $absPath = [this.path ?? "", $path].join(".").replace(/^\.+/, "");
|
|
1281
|
+
if (Array.isArray($rawValue) && !this.isArrayContainer($absPath)) {
|
|
1282
|
+
$field.value = parseInput(applyInputConverterOnUpdate ? $field.$input : (val) => val, {
|
|
1283
|
+
fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
|
|
1284
|
+
separated: $rawValue,
|
|
1285
|
+
});
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1275
1288
|
if (Array.isArray($field.values())) {
|
|
1276
1289
|
const n = Math.max(-1, ...Object.keys(field.fields || {}).map(Number));
|
|
1277
1290
|
getObservableMapValues($field.fields).forEach(($f) => {
|
|
@@ -1309,17 +1322,18 @@
|
|
|
1309
1322
|
// init field into the container field
|
|
1310
1323
|
$container.$changed++;
|
|
1311
1324
|
$container.state.form.$changed++;
|
|
1312
|
-
|
|
1325
|
+
// the value provided by the update wins over the declared values
|
|
1326
|
+
$container.initField($key, $newFieldPath, field, true, lodash.get(raw, $path));
|
|
1313
1327
|
}
|
|
1314
1328
|
else if (recursion) {
|
|
1315
1329
|
if (lodash.has(field, FieldPropsEnum.fields) && field.fields != null) {
|
|
1316
1330
|
// handle nested fields if defined
|
|
1317
|
-
this.deepUpdate(field.fields, $path);
|
|
1331
|
+
this.deepUpdate(field.fields, $path, true, raw);
|
|
1318
1332
|
}
|
|
1319
1333
|
else {
|
|
1320
1334
|
// handle nested fields if undefined or null
|
|
1321
1335
|
const $fields = pathToFieldsTree(this.state.struct(), $path);
|
|
1322
|
-
this.deepUpdate($fields, $path, false);
|
|
1336
|
+
this.deepUpdate($fields, $path, false, raw);
|
|
1323
1337
|
}
|
|
1324
1338
|
}
|
|
1325
1339
|
});
|
|
@@ -1494,7 +1508,36 @@
|
|
|
1494
1508
|
execEvent && this.execHook(FieldPropsEnum.onAdd);
|
|
1495
1509
|
return this;
|
|
1496
1510
|
}
|
|
1497
|
-
|
|
1511
|
+
// a plain field holding an array value gets the new item appended
|
|
1512
|
+
if (this.isPlainArrayField() &&
|
|
1513
|
+
!lodash.has(obj, FieldPropsEnum.key) &&
|
|
1514
|
+
!lodash.has(obj, FieldPropsEnum.name)) {
|
|
1515
|
+
const $values = Array.isArray(this.value)
|
|
1516
|
+
? [...this.value]
|
|
1517
|
+
: [];
|
|
1518
|
+
$values.push(lodash.has(obj, FieldPropsEnum.value)
|
|
1519
|
+
? obj[FieldPropsEnum.value]
|
|
1520
|
+
: defaultValue({
|
|
1521
|
+
fallbackValueOption: this.state.options.get(OptionsEnum.fallbackValue, this),
|
|
1522
|
+
nullable: this.$nullable,
|
|
1523
|
+
type: this.type,
|
|
1524
|
+
}));
|
|
1525
|
+
this.set(FieldPropsEnum.value, $values);
|
|
1526
|
+
this.$changed++;
|
|
1527
|
+
this.state.form.$changed++;
|
|
1528
|
+
execEvent && this.execHook(FieldPropsEnum.onAdd);
|
|
1529
|
+
return this;
|
|
1530
|
+
}
|
|
1531
|
+
const field = this.createField(obj);
|
|
1532
|
+
this.$changed++;
|
|
1533
|
+
this.state.form.$changed++;
|
|
1534
|
+
execEvent && this.execHook(FieldPropsEnum.onAdd);
|
|
1535
|
+
return field;
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
Create a new field into this container (no change counters, no hooks)
|
|
1539
|
+
*/
|
|
1540
|
+
createField(obj, key) {
|
|
1498
1541
|
const tree = pathToFieldsTree(this.state.struct(), this.path ?? "", 0, true);
|
|
1499
1542
|
const nestedFields = tree[0]?.fields ?? null;
|
|
1500
1543
|
// An object without field-definition props, whose keys match the
|
|
@@ -1512,14 +1555,14 @@
|
|
|
1512
1555
|
payloadKeys.length > 0 &&
|
|
1513
1556
|
(!lodash.has(obj, FieldPropsEnum.name) ||
|
|
1514
1557
|
Object.prototype.hasOwnProperty.call(nestedFields, FieldPropsEnum.name));
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
const $path = ($
|
|
1522
|
-
const field = this.initField(
|
|
1558
|
+
const $key = key ?? obj?.[FieldPropsEnum.key];
|
|
1559
|
+
const $fieldKey = $key !== void 0
|
|
1560
|
+
? $key
|
|
1561
|
+
: !isValuesPayload && obj?.[FieldPropsEnum.name] !== void 0
|
|
1562
|
+
? obj[FieldPropsEnum.name]
|
|
1563
|
+
: maxKey(this.fields);
|
|
1564
|
+
const $path = ($k) => [this.path, $k].join(".").replace(/^\.+/, "");
|
|
1565
|
+
const field = this.initField($fieldKey, $path($fieldKey), isValuesPayload ? tree[0] : lodash.merge(tree[0], obj), false, lodash.has(obj, FieldPropsEnum.value) ? obj[FieldPropsEnum.value] : void 0);
|
|
1523
1566
|
const hasValues = lodash.has(obj, FieldPropsEnum.value) || lodash.has(obj, FieldPropsEnum.fields);
|
|
1524
1567
|
if (isValuesPayload) {
|
|
1525
1568
|
lodash.each(payloadKeys, (fieldName) => {
|
|
@@ -1559,11 +1602,71 @@
|
|
|
1559
1602
|
})));
|
|
1560
1603
|
}
|
|
1561
1604
|
}
|
|
1562
|
-
this.$changed++;
|
|
1563
|
-
this.state.form.$changed++;
|
|
1564
|
-
execEvent && this.execHook(FieldPropsEnum.onAdd);
|
|
1565
1605
|
return field;
|
|
1566
1606
|
}
|
|
1607
|
+
/**
|
|
1608
|
+
Checks if the given path refers to an array container
|
|
1609
|
+
(a struct entry like `path[]` or `path[].subfield`)
|
|
1610
|
+
*/
|
|
1611
|
+
isArrayContainer(path) {
|
|
1612
|
+
const struct = this.state.struct();
|
|
1613
|
+
if (!Array.isArray(struct))
|
|
1614
|
+
return false;
|
|
1615
|
+
const structPath = (path ?? this.path ?? "").replace(/\.\d+\./g, "[].");
|
|
1616
|
+
return struct.some((s) => typeof s === "string" && s.startsWith(`${structPath}[]`));
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
Checks if the field is a plain field holding an array value
|
|
1620
|
+
(not an array container with nested fields)
|
|
1621
|
+
*/
|
|
1622
|
+
isPlainArrayField() {
|
|
1623
|
+
return (!this.hasNestedFields &&
|
|
1624
|
+
!this.isArrayContainer(this.path ?? "") &&
|
|
1625
|
+
Array.isArray(this.value));
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
Applies a value to a field: for fields with nested fields the value is
|
|
1629
|
+
applied to the nested fields, otherwise the field value is set
|
|
1630
|
+
*/
|
|
1631
|
+
applyValue($field, value) {
|
|
1632
|
+
if (value === void 0)
|
|
1633
|
+
return;
|
|
1634
|
+
if (lodash.isPlainObject(value) && $field.fields.size) {
|
|
1635
|
+
lodash.each(value, (val, key) => {
|
|
1636
|
+
const $nested = $field.select(key);
|
|
1637
|
+
if ($nested) {
|
|
1638
|
+
$nested.fields.size
|
|
1639
|
+
? this.applyValue($nested, val)
|
|
1640
|
+
: $nested.set(FieldPropsEnum.value, val);
|
|
1641
|
+
}
|
|
1642
|
+
});
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
$field.set(FieldPropsEnum.value, value);
|
|
1646
|
+
}
|
|
1647
|
+
/**
|
|
1648
|
+
Writes an array of values into an array container: the nested fields are
|
|
1649
|
+
created, updated and removed to match the given array
|
|
1650
|
+
*/
|
|
1651
|
+
applyArrayValue($field, values) {
|
|
1652
|
+
// remove the nested fields which are not in the new values
|
|
1653
|
+
getObservableMapValues($field.fields).forEach(($f) => {
|
|
1654
|
+
if (Number($f.name) >= values.length) {
|
|
1655
|
+
$field.fields.delete($f.name);
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
// create or update the nested fields
|
|
1659
|
+
values.forEach((value, index) => {
|
|
1660
|
+
const key = String(index);
|
|
1661
|
+
const $nested = $field.fields.get(key);
|
|
1662
|
+
if ($nested) {
|
|
1663
|
+
this.applyValue($nested, value);
|
|
1664
|
+
}
|
|
1665
|
+
else {
|
|
1666
|
+
$field.createField(lodash.isPlainObject(value) ? value : { [FieldPropsEnum.value]: value }, key);
|
|
1667
|
+
}
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1567
1670
|
/**
|
|
1568
1671
|
Del Field
|
|
1569
1672
|
*/
|
|
@@ -2616,19 +2719,24 @@
|
|
|
2616
2719
|
/* EVENTS HANDLERS */
|
|
2617
2720
|
sync = mobx.action((e, v = null) => {
|
|
2618
2721
|
const $get = ($) => isBool($, this.value) ? $.target.checked : $.target.value;
|
|
2619
|
-
//
|
|
2722
|
+
// resolve the value to be set
|
|
2723
|
+
let $value;
|
|
2620
2724
|
if (lodash.isNil(e) || lodash.isNil(e.target)) {
|
|
2621
2725
|
if (!lodash.isNil(v) && !lodash.isNil(v.target)) {
|
|
2622
2726
|
v = $get(v); // eslint-disable-line
|
|
2623
2727
|
}
|
|
2624
|
-
|
|
2625
|
-
|
|
2728
|
+
$value = $try(e, v);
|
|
2729
|
+
}
|
|
2730
|
+
else {
|
|
2731
|
+
$value = $get(e);
|
|
2626
2732
|
}
|
|
2627
|
-
|
|
2628
|
-
|
|
2733
|
+
// an array set on a field with nested fields is applied to the nested
|
|
2734
|
+
// fields, otherwise the value would be silently dropped
|
|
2735
|
+
if (this.hasNestedFields && Array.isArray($value)) {
|
|
2736
|
+
this.state.form.applyArrayValue(this, $value);
|
|
2629
2737
|
return;
|
|
2630
2738
|
}
|
|
2631
|
-
this.value =
|
|
2739
|
+
this.value = $value;
|
|
2632
2740
|
});
|
|
2633
2741
|
onSync = (...args) => this.type === "file"
|
|
2634
2742
|
? this.onDrop(...args)
|
|
@@ -2832,7 +2940,13 @@
|
|
|
2832
2940
|
nullable: this.$nullable,
|
|
2833
2941
|
type: this.type,
|
|
2834
2942
|
});
|
|
2835
|
-
|
|
2943
|
+
if (this.isArrayContainer(this.path ?? "") && Array.isArray(this.value)) {
|
|
2944
|
+
// an array container is emptied: the nested fields are removed
|
|
2945
|
+
getObservableMapValues(this.fields).forEach(($f) => this.fields.delete($f.name));
|
|
2946
|
+
}
|
|
2947
|
+
else {
|
|
2948
|
+
deep && this.each((field) => field.clear(deep));
|
|
2949
|
+
}
|
|
2836
2950
|
this.state.options.get(OptionsEnum.validateOnClear, this)
|
|
2837
2951
|
? this.validate({
|
|
2838
2952
|
showErrors: this.state.options.get(OptionsEnum.showErrorsOnClear, this),
|
|
@@ -2847,11 +2961,31 @@
|
|
|
2847
2961
|
this.$changed = 0;
|
|
2848
2962
|
this.files = undefined;
|
|
2849
2963
|
const useDefaultValue = this.$default !== this.$initial;
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2964
|
+
const $target = useDefaultValue ? this.$default : this.$initial;
|
|
2965
|
+
if (this.isArrayContainer(this.path ?? "") &&
|
|
2966
|
+
!useDefaultValue &&
|
|
2967
|
+
Array.isArray($target)) {
|
|
2968
|
+
// an array container is rebuilt from its initial (or default) array:
|
|
2969
|
+
// the removed nested fields are restored and the added ones dropped
|
|
2970
|
+
const $values = $target;
|
|
2971
|
+
const $fields = getObservableMapValues(this.fields);
|
|
2972
|
+
const $match = $fields.length === $values.length &&
|
|
2973
|
+
$fields.every(($f, i) => lodash.isEqual($f.value, $values[i]));
|
|
2974
|
+
if (!$match) {
|
|
2975
|
+
$fields.forEach(($f) => this.fields.delete($f.name));
|
|
2976
|
+
$values.forEach((value, index) => this.createField(lodash.isPlainObject(value) ? value : { [FieldPropsEnum.value]: value }, String(index)));
|
|
2977
|
+
}
|
|
2978
|
+
else {
|
|
2979
|
+
deep && this.each((field) => field.reset(deep));
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
else {
|
|
2983
|
+
if (useDefaultValue)
|
|
2984
|
+
this.value = this.$default;
|
|
2985
|
+
if (!useDefaultValue)
|
|
2986
|
+
this.value = this.$initial;
|
|
2987
|
+
deep && this.each((field) => field.reset(deep));
|
|
2988
|
+
}
|
|
2855
2989
|
this.state.options.get(OptionsEnum.validateOnReset, this)
|
|
2856
2990
|
? this.validate({
|
|
2857
2991
|
showErrors: this.state.options.get(OptionsEnum.showErrorsOnReset, this),
|