Skip to content

Commit edc70d7

Browse files
committed
setValues now accepts undefined
1 parent 28097e9 commit edc70d7

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

example/src/App.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@ export function Form() {
303303
<button type="button" onClick={() => form.setErrors("This is a parent error")}>
304304
Set parent error
305305
</button>
306-
j
307306
</div>
308307
</VisualRender>
309308
)}

src/form.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,7 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
141141
}
142142

143143
/**
144-
* Sets a value the advanced way.
145-
* @param key The field to set.
146-
* @param value The value to set in the field.
144+
* Sets a value without calculating whether is has been modified.
147145
* @param dirty Is this field dirty? Leave undefined to not set any dirty value. (can always be overridden by child forms)
148146
* @param validate Should the form validate after value set? Overrides `validateOnChange`.
149147
* @param isDefault Is this the default value for the said field?
@@ -163,8 +161,12 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
163161
) {
164162
let valueMap = isDefault ? this.defaultValues : this.values;
165163
if (value === undefined) {
166-
if (Array.isArray(valueMap)) valueMap.splice(key as number, 1);
167-
else delete valueMap[key];
164+
if (Array.isArray(valueMap)) {
165+
// Deleting a key in an array doesn't work, splice instead
166+
valueMap.splice(key as number, 1);
167+
} else {
168+
delete valueMap[key];
169+
}
168170
} else {
169171
valueMap[key] = value;
170172
}
@@ -173,8 +175,8 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
173175

174176
if (notifyChild) {
175177
let child = this.childMap[key];
176-
if (child && value !== undefined && value !== null) {
177-
child.setValues(value!, validate, isDefault, true, false);
178+
if (child) {
179+
child.setValues(value, validate, isDefault, true, false);
178180
this.dirtyMap[key] = child.dirty;
179181
}
180182
}
@@ -258,36 +260,47 @@ export class FormState<T, State = DefaultState, Error extends string = DefaultEr
258260
* @param notifyChild Should this form notify the child form about this change?
259261
* @param notifyParent Should this form notify the parent form about this change?
260262
*/
261-
public setValues(values: Partial<T>, validate?: boolean, isDefault: boolean = false, notifyChild: boolean = true, notifyParent: boolean = true) {
263+
public setValues(
264+
values: Partial<T> | undefined,
265+
validate?: boolean,
266+
isDefault: boolean = false,
267+
notifyChild: boolean = true,
268+
notifyParent: boolean = true
269+
) {
262270
let keys = Object.keys(isDefault ? this.defaultValues : this.values);
263-
addDistinct(keys, Object.keys(values));
271+
let v: typeof values = values ?? {};
272+
addDistinct(keys, Object.keys(v));
264273

265274
// Traverse backwards, so when removing array items, the whole array gets shifted in the right direction
266275
for (let i = keys.length - 1; i >= 0; i--) {
267276
let key = keys[i] as keyof T;
268277
this.setValue(
269278
key,
270-
values[key],
279+
v[key],
271280
false, // Will validate after all values are copied
272281
isDefault,
273282
notifyChild,
274283
false, // Will call updateParentValues by itself after all values are copied, see 3 lines down
275284
false // Will call fireAnyListener by itself after all values are copied, see 3 lines down
276285
);
277286
}
287+
278288
this.fireAnyListeners();
279289
if (notifyParent && this instanceof ChildFormState) {
280-
let values = isDefault ? memberCopy(this.defaultValues) : memberCopy(this.values);
281-
this.parent.setValueInternal(
282-
this.name,
283-
Object.keys(values).length > 0 ? values : undefined,
284-
this.dirty,
285-
validate,
286-
isDefault,
287-
false,
288-
true,
289-
true
290-
);
290+
if (typeof values === "object" && values !== null) {
291+
this.parent.setValueInternal(
292+
this.name,
293+
isDefault ? memberCopy(this.defaultValues) : memberCopy(this.values),
294+
this.dirty,
295+
validate,
296+
isDefault,
297+
false,
298+
true,
299+
true
300+
);
301+
} else {
302+
this.parent.setValueInternal(this.name, values, this.dirty, validate, isDefault, false, true, true);
303+
}
291304
}
292305

293306
if (validate ?? (this.validateOnChange && this.validator)) this.validate();

src/hooks.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ export function useChildForm<T, Key extends keyof T, State = DefaultState, Error
5959
c.current!.name = name;
6060

6161
// First, set new default values, without validating
62-
c.current!.setValues(parentForm.defaultValues[name] ?? {}, false, true, true, false);
62+
c.current!.setValues(parentForm.defaultValues[name], false, true, true, false);
6363
// Then, set new values and validate if needed
64-
c.current!.setValues(parentForm.values[name] ?? {}, c.current!.validateOnMount, false, true, true);
64+
c.current!.setValues(parentForm.values[name], c.current!.validateOnMount, false, true, true);
6565

6666
return () => {
6767
// Only delete if is not already overwritten by new form
@@ -117,7 +117,9 @@ export function useAnyListener<T, State = DefaultState, Error extends string = D
117117
let id = form.listenAny(() => {
118118
setRender((e) => e + 1);
119119
});
120-
return () => form.ignoreAny(id);
120+
return () => {
121+
form.ignoreAny(id);
122+
};
121123
}, [form]);
122124

123125
return form;

0 commit comments

Comments
 (0)