@homebound/form-state 2.22.2 → 2.22.3
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.
|
@@ -163,6 +163,8 @@ function newObjectState(config, parentState, parentListState, instance, key, may
|
|
|
163
163
|
get changedValue() {
|
|
164
164
|
const result = {};
|
|
165
165
|
getFields(this).forEach((f) => {
|
|
166
|
+
if (f._computed)
|
|
167
|
+
return;
|
|
166
168
|
if (f.dirty ||
|
|
167
169
|
// If the caller used useFormState.ifUndefined to provide some default values, then those keys may not
|
|
168
170
|
// look dirty, but if we're new we should include them anyway.
|
|
@@ -18,6 +18,8 @@ function newValueFieldState(parentCopy, parentInstance, parentState, key, rules,
|
|
|
18
18
|
_readOnly: readOnly || false,
|
|
19
19
|
_loading: false,
|
|
20
20
|
_focused: false,
|
|
21
|
+
// Expose so computed can be skipped in changedValue
|
|
22
|
+
_computed: computed,
|
|
21
23
|
_isIdKey: isIdKey,
|
|
22
24
|
_isDeleteKey: isDeleteKey,
|
|
23
25
|
_isReadOnlyKey: isReadOnlyKey,
|
|
@@ -54,6 +56,12 @@ function newValueFieldState(parentCopy, parentInstance, parentState, key, rules,
|
|
|
54
56
|
},
|
|
55
57
|
// For primitive fields, the changed value is just the value.
|
|
56
58
|
get changedValue() {
|
|
59
|
+
// Usually if we see a field being unset, we set `parent[key] = null`, but if we're wrapping
|
|
60
|
+
// a mobx observable object, it might have changed to `undefined` without us being able to
|
|
61
|
+
// tell it to be `null` (and potentially break the type contract of `string | undefined`).
|
|
62
|
+
// So detect un-set-ness here and return `null`.
|
|
63
|
+
if (this.value === undefined && this.originalValue !== undefined)
|
|
64
|
+
return null;
|
|
57
65
|
return this.value;
|
|
58
66
|
},
|
|
59
67
|
get valid() {
|
package/dist/formState.test.js
CHANGED
|
@@ -979,11 +979,7 @@ describe("formState", () => {
|
|
|
979
979
|
it("can observe observable objects being mutated directly", () => {
|
|
980
980
|
// Given a mobx class with a computed
|
|
981
981
|
const instance = new ObservableObject();
|
|
982
|
-
const formState = (0, objectField_1.createObjectState)(
|
|
983
|
-
firstName: { type: "value" },
|
|
984
|
-
lastName: { type: "value" },
|
|
985
|
-
fullName: { type: "value", computed: true },
|
|
986
|
-
}, instance);
|
|
982
|
+
const formState = (0, objectField_1.createObjectState)(authorWithFullName, instance);
|
|
987
983
|
expect(formState.firstName.value).toEqual("first");
|
|
988
984
|
expect(formState.fullName.value).toEqual("first last");
|
|
989
985
|
// And we hook up reactivity to the computed
|
|
@@ -999,9 +995,11 @@ describe("formState", () => {
|
|
|
999
995
|
expect(formState.fullName.value).toEqual("change last");
|
|
1000
996
|
// And when the underlying mobx class has a field unset
|
|
1001
997
|
instance.firstName = undefined;
|
|
1002
|
-
// Then our
|
|
998
|
+
// Then our form-state computed re-runs again
|
|
1003
999
|
expect(numCalcs).toBe(3);
|
|
1004
1000
|
expect(formState.fullName.value).toEqual("undefined last");
|
|
1001
|
+
// And knows the field should be sent as null
|
|
1002
|
+
expect(formState.changedValue).toEqual({ firstName: null });
|
|
1005
1003
|
});
|
|
1006
1004
|
it("can set computeds that have setters", () => {
|
|
1007
1005
|
const formState = (0, objectField_1.createObjectState)({
|
|
@@ -1086,6 +1084,18 @@ describe("formState", () => {
|
|
|
1086
1084
|
// because this might trigger creating a throw-away entity
|
|
1087
1085
|
expect(formState.changedValue).toEqual({ firstName: "f" });
|
|
1088
1086
|
});
|
|
1087
|
+
it("changedValue skips computeds", () => {
|
|
1088
|
+
// Given a new author that calls full name
|
|
1089
|
+
const formState = (0, objectField_1.createObjectState)(authorWithFullName, new ObservableObject());
|
|
1090
|
+
expect(formState.fullName.value).toEqual("first last");
|
|
1091
|
+
// When the firstName changes
|
|
1092
|
+
formState.firstName.value = "First";
|
|
1093
|
+
// Then the fullName changes
|
|
1094
|
+
expect(formState.fullName.value).toBe("First last");
|
|
1095
|
+
expect(formState.fullName.dirty).toBe(true);
|
|
1096
|
+
// And we don't include it in the changedValue
|
|
1097
|
+
expect(formState.changedValue).toEqual({ firstName: "First" });
|
|
1098
|
+
});
|
|
1089
1099
|
it("can return only changed list fields", () => {
|
|
1090
1100
|
// Given an author with some books
|
|
1091
1101
|
const formState = (0, objectField_1.createObjectState)(authorWithBooksConfig, {
|
|
@@ -1579,6 +1589,11 @@ const authorWithBooksConfig = configBuilders_1.f.config({
|
|
|
1579
1589
|
function createAuthorInputState(input, maybeAutoSave) {
|
|
1580
1590
|
return (0, objectField_1.createObjectState)(authorWithBooksConfig, input, { maybeAutoSave });
|
|
1581
1591
|
}
|
|
1592
|
+
const authorWithFullName = {
|
|
1593
|
+
firstName: { type: "value" },
|
|
1594
|
+
lastName: { type: "value" },
|
|
1595
|
+
fullName: { type: "value", computed: true },
|
|
1596
|
+
};
|
|
1582
1597
|
const authorWithAddressConfig = {
|
|
1583
1598
|
id: { type: "value" },
|
|
1584
1599
|
firstName: { type: "value" },
|