Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/poor-yaks-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': minor
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'@sveltejs/kit': minor
'@sveltejs/kit': patch

---

feat: Add "hidden number" and "hidden boolean" input types for remote form fields
8 changes: 7 additions & 1 deletion packages/kit/src/exports/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,8 @@ type InputTypeMap = {
radio: string;
file: File;
hidden: string;
'hidden boolean': boolean;
'hidden number': number;
submit: string;
button: string;
reset: string;
Expand Down Expand Up @@ -1890,7 +1892,11 @@ type AsArgs<Type extends keyof InputTypeMap, Value> = Type extends 'checkbox'
: [type: Type]
: Type extends 'radio' | 'submit' | 'hidden'
? [type: Type, value: Value | (string & {})]
: [type: Type];
: Type extends 'hidden number'
? [type: Type, value: Value | (number & {})]
: Type extends 'hidden boolean'
? [type: Type, value: Value | (boolean & {})]
: [type: Type];

/**
* Form field accessor type that provides name(), value(), and issues() methods
Expand Down
32 changes: 29 additions & 3 deletions packages/kit/src/runtime/form-utils.svelte.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
if (prop === 'as') {
/**
* @param {string} type
* @param {string} [input_value]
* @param {string | number | boolean} [input_value]
*/
const as_func = (type, input_value) => {
const is_array =
Expand All @@ -258,9 +258,9 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
(type === 'checkbox' && typeof input_value === 'string');

const prefix =
type === 'number' || type === 'range'
type === 'number' || type === 'range' || type === 'hidden number'
? 'n:'
: type === 'checkbox' && !is_array
: (type === 'checkbox' && !is_array) || type === 'hidden boolean'
? 'b:'
: '';

Expand Down Expand Up @@ -292,6 +292,32 @@ export function create_field_proxy(target, get_input, depend, set_input, get_iss
});
}

// Handle hidden number inputs
if (type === 'hidden number') {
if (DEV) {
if (typeof input_value !== 'number') {
throw new Error(`\`hidden number\` input must be a number value.`);
}
}

return Object.defineProperties(base_props, {
value: { value: input_value, enumerable: true }
});
}

// Handle hidden boolean inputs
if (type === 'hidden boolean') {
if (DEV) {
if (typeof input_value !== 'boolean') {
throw new Error(`\`hidden boolean\` input must be a boolean value.`);
}
}

return Object.defineProperties(base_props, {
value: { value: input_value && 'on', enumerable: true }
});
}

// Handle select inputs
if (type === 'select' || type === 'select multiple') {
return Object.defineProperties(base_props, {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
import { get_hidden, set_hidden } from './form.remote';
const hidden = get_hidden();
</script>

<!-- TODO use await here once async lands -->
{#await hidden then h}
<p>await hidden().string: {h.string}</p>
<p>await hidden().number: {h.number}</p>
<p>await hidden().boolean: {h.boolean}</p>
{/await}

<form {...set_hidden}>
<input {...set_hidden.fields.string.as('hidden', 'b')} />
<input {...set_hidden.fields.number.as('hidden number', 1)} />
<input {...set_hidden.fields.boolean.as('hidden boolean', true)} />
<button>set hidden</button>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { form, query } from '$app/server';
import * as v from 'valibot';

let hidden = {
string: 'a',
number: 0,
boolean: false
};

export const get_hidden = query(() => {
return hidden;
});

export const set_hidden = form(
v.object({
string: v.string(),
number: v.number(),
boolean: v.boolean()
}),
async (data) => {
hidden = data;
get_hidden().refresh();
}
);
14 changes: 14 additions & 0 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,20 @@ test.describe('remote functions', () => {
await expect(page.locator('#result')).toHaveText('hello');
});

test('form hidden inputs of different types work', async ({ page, javaScriptEnabled }) => {
await page.goto('/remote/form/hidden');

await page.locator('button').click();

if (javaScriptEnabled) {
await expect(page.getByText('await hidden().string:')).toHaveText('await hidden().string: b');
await expect(page.getByText('await hidden().number:')).toHaveText('await hidden().number: 1');
await expect(page.getByText('await hidden().boolean:')).toHaveText(
'await hidden().boolean: true'
);
}
});

test('form updates inputs live', async ({ page, javaScriptEnabled }) => {
await page.goto('/remote/form');

Expand Down
8 changes: 7 additions & 1 deletion packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1809,6 +1809,8 @@ declare module '@sveltejs/kit' {
radio: string;
file: File;
hidden: string;
'hidden boolean': boolean;
'hidden number': number;
submit: string;
button: string;
reset: string;
Expand Down Expand Up @@ -1866,7 +1868,11 @@ declare module '@sveltejs/kit' {
: [type: Type]
: Type extends 'radio' | 'submit' | 'hidden'
? [type: Type, value: Value | (string & {})]
: [type: Type];
: Type extends 'hidden number'
? [type: Type, value: Value | (number & {})]
: Type extends 'hidden boolean'
? [type: Type, value: Value | (boolean & {})]
: [type: Type];

/**
* Form field accessor type that provides name(), value(), and issues() methods
Expand Down
Loading