Skip to main content

SvelteKit form checkboxes not accurately displaying checked state after form submission

I have a SvelteKit route with a +page.server.ts file which has a load function that retrieves a user record from a database. The user has a string property containing a comma delimited list of "collection" ids that user has access to. In the +page.svelte page, I display a form with checkboxes for each collection to allow an admin user to grant or revoke permissions to collections. Here is my code for displaying the checkboxes

<form method="post" action="?/setCollections" use:enhance>
            <input type="hidden" name="email" value={data.user.email} />
            <fieldset style:padding-left="1rem">
                {#each data.collections as collection (collection.id)}
                    <div style:margin-bottom=".5rem">
                        <input
                            id={collection.name}
                            name={collection.name}
                            type="checkbox"
                            value={collection.id}
                            checked={data.user.collections?.includes(collection.id)}
                        />
                        <label for={collection.name}>
                            <small>{collection.name} ({data.user.collections?.includes(collection.id)})</small>
                        </label>
                    </div>
                {/each}
            </fieldset>
            <button style:margin-top="1rem" type="submit">Save</button>
        </form>

On page load, it is displaying the checkboxes correctly. However, in the scenario where checkboxes B and C are checked, and the admin user checks checkbox A with the intention of giving the user access to A, B and C and submits the form, the page rerenders and only checkbox A is left in the checked state. I can't figure out why this is happening, because the value passed to the checked property for checkboxes B and C is still true, as can be seen by the debug text in the label

enter image description here

The form action is defined in the +page.server.ts actions object, and is here. My method for iterating the checkbox values is probably not ideal but I do not think this is the issue, as the value in the database is being updated correctly.

setCollections: async ({ request }) => {
        const data = await request.formData();
        const email = data.get('email')?.toString();
        // Pop email from values so we can iterate only the checkboxes
        data.delete('email');

        let collections = '';
        // Iterate collections and add to the string
        for (const [key, value] of data.entries()) {
            collections += value;
            const nextVal = [...data.keys()].pop();
            // Delimit with a comma if not the last item
            if (nextVal && data.get(nextVal) !== data.get(key)) collections += ',';
        }

        const client = new DynamoDBClient();

        const docClient = DynamoDBDocumentClient.from(client);

        const updateCommand: UpdateCommandInput = {
            TableName: 'users',
            Key: {
                email
            },
            UpdateExpression: 'set collections = :collections',
            ExpressionAttributeValues: {
                ':collections': collections
            }
        };

        const command = new UpdateCommand(updateCommand);

        const response = await docClient.send(command);

        return { message: 'User collection permissions were updated.' };
    }

This is probably due to my lack of knowledge in something related to SvelteKit. I have tried assigning the collections to a variable on page load instead like $: collections = data.user?.collections.split(",") ?? [] and using bind:group on this variable, but still does not work and I can't seem to find my mistake.

Via Active questions tagged javascript - Stack Overflow https://ift.tt/DA1eBNM

Comments