-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
Description
I'm getting an issue where the fields get "linked" (writing in on field updates all of them, except the initial fieldset) when adding a new fieldset (i.e. formHandler.addFieldset({ basePath: "contacts" })).
Ex.
- Initial contact
#1(not affected by subsequent fieldsets) - Add new contact
#2and fill in all required fields, then create another contact (#3) - Last contact
#3will be added with the data from fieldsname.firstandname.lastin contact#2 - Changing values in contact
#2or#3will change in both, contact#1is not affected
An obvious an easy fix (in this scenario) is to just change the schema (see below) so the names (first and last) aren't in a new object level, i.e. firstName and lastName. But for other cases this might not be optimal, e.g. someDeepObjectLevelStructureOne (...two, etc) which maybe should have been some.deep.object.level.structure.one.
ZOD schema excerpt:
const schema = z.object({
...
contacts: z.array(
z.object({
name: z.object({
first: z.string().min(2, "Minimum 2 characters"),
last: z.string().min(2, "Minimum 2 characters"),
}),
email: z.string().email("Incorrect contact email"),
phone: z.string().min(5, "Minimum 5 characters").optional().or(z.literal("")),
password: z.string().min(8, "Minimum 8 characters").optional().or(z.literal("")),
createUser: z.boolean().default(false),
}),
).min(1, "There must be at least one (1) contact person for a client"),
});Usage/Code excerpt:
<h3 class="h2">Contacts</h3>
<HorizontalDivider margin={4} />
<section>
<ul>
<For each={formHandler.formData().contacts}>
{(contact, index) => (
<li
class={cn(
"relative mb-8 grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-x-8 sm:gap-y-0",
{
"mt-4 border-t border-t-gray-200 pt-8": index() > 0,
},
)}
>
<div class="col-span-2 flex w-full items-center justify-end gap-x-2">
{formHandler.formData().contacts.length > 1 && (
<div class="text-sm text-gray-400">
# {index() + 1}
</div>
)}
{index() > 0 && (
<Button
iconOnly
round
flush
leadingIcon={Icons.CANCEL}
leadingIconSize={Size.SM}
color={Colors.DESTRUCTIVE}
{...(!isWorking() && {
onClick: () => formHandler.removeFieldset(index(), "contacts"),
})}
/>
)}
</div>
<FormField
label="First name"
placeholder={index() % 2 === 0 ? "John" : "Jane"}
id={`contacts.${index()}.name.first`}
name={`contacts.${index()}.name.first`}
/>
<FormField
label="Last name"
placeholder="Doe"
id={`contacts.${index()}.name.last`}
name={`contacts.${index()}.name.last`}
/>
<FormField
label="email"
placeholder={`${index() % 2 === 0 ? "john" : "jane"}.doe@email.com`}
id={`contacts.${index()}.email`}
name={`contacts.${index()}.email`}
/>
<FormField
label="Phone (optional)"
id={`contacts.${index()}.phone`}
name={`contacts.${index()}.phone`}
/>
<Show when={contact.createUser}>
<FormField
label="password"
name={`contacts.${index()}.password`}
type={InputType.PASSWORD}
toggleShowPassword
required
autocomplete="password"
/>
</Show>
<FormCheckbox
onClick={() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
formHandler.setFieldValue(`contacts.${index()}.createUser`, !`contacts.${index()}.createUser`);
if (contact.createUser) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
formHandler.setFieldValue(`contacts.${index()}.createUser`, undefined);
} else {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
formHandler.setFieldValue(`contacts.${index()}.password`, generatePassword());
}
}}
class="col-span-2"
id={`contacts.${index()}.createUser`}
name={`contacts.${index()}.createUser`}
label="Create user account"
hint="Select if you want to creat a user account, with the “owner” role, in the client for this contact"
/>
</li>
)}
</For>
</ul>
<Button
leadingIcon={Icons.ADD}
onClick={() => formHandler.addFieldset({ basePath: "contacts" })}
disabled={isWorking() || !canAddUser()}
>
add contact
</Button>
</section>mauriver21