Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form implementation only allows flat objects #8

Open
ebetulo opened this issue Mar 7, 2025 · 1 comment
Open

Form implementation only allows flat objects #8

ebetulo opened this issue Mar 7, 2025 · 1 comment

Comments

@ebetulo
Copy link

ebetulo commented Mar 7, 2025

Onbezorgd Ontslag backend has a POSt route that requires data in a certain shape:

curl --request POST \
    "https://admin.onbezorgd-ontslag.igne.link/api/cases/9e3fcaa1-3b0c-4572-89c8-dbb003d10f4c/contact-persons" \
    --header "Authorization: Bearer {TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"contact_persons\": [
        {
            \"id\": \"c2d28dff-2155-48df-b3bb-e3349223ee88\",
            \"first_name\": \"Jan\",
            \"infix\": \"van der\",
            \"last_name\": \"Veen\",
            \"job_title\": \"CEO\",
            \"email\": \"jan@example.com\",
            \"phone_number\": \"0612345678\"
        }
    ]
}"

There is no way to map the shape of the data returned by a form submit event before it got passed to the validator. We could either validate the flat structure and map it after validating but before posting, but we decided to allow a transform function as part of the form that runs on the data before validation. We solved it with the following code:

export const deepenFlatObject = (data: object): object => {
	return Object.entries(data).reduce((acc, [key, value]) => {
		const path = key.split(".");
		let target = acc;
		for (let i = 0; i < path.length - 1; i++) {
			const key = path[i];
			const isArray = /^\d+$/.test(path[i + 1]);
			target[key] ??= isArray ? [] : {};
			target = target[key];
		}
		// biome-ignore lint/style/noNonNullAssertion: Last item is always defined
		target[path.at(-1)!] = value;
		return acc;
		// biome-ignore lint/suspicious/noExplicitAny: We know what we're doing
	}, {} as any);
};

It would be nice if we had a standard implementation for this in the template.

@igne-wouter
Copy link
Collaborator

igne-wouter commented Mar 7, 2025

Good point.

I'm unsure if this is something we actually want to happen in forms? This is what react-zorm did for us, but that package had its issues so we moved away from it.

As for a implementation, we might want to depend on dot-object, which does this (among other things) and is a little more battle-tested.

@publicJorn What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants