93 lines
3.1 KiB
Svelte
Executable File
93 lines
3.1 KiB
Svelte
Executable File
<!-- [DEF:DynamicForm:Component] -->
|
|
<!--
|
|
@SEMANTICS: form, schema, dynamic, json-schema
|
|
@PURPOSE: Generates a form dynamically based on a JSON schema.
|
|
@LAYER: UI
|
|
@RELATION: DEPENDS_ON -> svelte:createEventDispatcher
|
|
|
|
@PROPS:
|
|
- schema: Object - JSON schema for the form.
|
|
@EVENTS:
|
|
- submit: Object - Dispatched when the form is submitted, containing the form data.
|
|
-->
|
|
<script>
|
|
// [SECTION: IMPORTS]
|
|
import { createEventDispatcher } from 'svelte';
|
|
// [/SECTION]
|
|
|
|
export let schema;
|
|
let formData = {};
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
// [DEF:handleSubmit:Function]
|
|
/**
|
|
* @purpose Dispatches the submit event with the form data.
|
|
* @pre formData contains user input.
|
|
* @post 'submit' event is dispatched with formData.
|
|
*/
|
|
function handleSubmit() {
|
|
console.log("[DynamicForm][Action] Submitting form data.", { formData });
|
|
dispatch('submit', formData);
|
|
}
|
|
// [/DEF:handleSubmit:Function]
|
|
|
|
// [DEF:initializeForm:Function]
|
|
/**
|
|
* @purpose Initialize form data with default values from the schema.
|
|
* @pre schema is provided and contains properties.
|
|
* @post formData is initialized with default values or empty strings.
|
|
*/
|
|
function initializeForm() {
|
|
if (schema && schema.properties) {
|
|
for (const key in schema.properties) {
|
|
formData[key] = schema.properties[key].default || '';
|
|
}
|
|
}
|
|
}
|
|
// [/DEF:initializeForm:Function]
|
|
|
|
initializeForm();
|
|
</script>
|
|
|
|
<!-- [SECTION: TEMPLATE] -->
|
|
<form on:submit|preventDefault={handleSubmit} class="space-y-4">
|
|
{#if schema && schema.properties}
|
|
{#each Object.entries(schema.properties) as [key, prop]}
|
|
<div class="flex flex-col">
|
|
<label for={key} class="mb-1 font-semibold text-gray-700">{prop.title || key}</label>
|
|
{#if prop.type === 'string'}
|
|
<input
|
|
type="text"
|
|
id={key}
|
|
bind:value={formData[key]}
|
|
placeholder={prop.description || ''}
|
|
class="p-2 border rounded-md"
|
|
/>
|
|
{:else if prop.type === 'number' || prop.type === 'integer'}
|
|
<input
|
|
type="number"
|
|
id={key}
|
|
bind:value={formData[key]}
|
|
placeholder={prop.description || ''}
|
|
class="p-2 border rounded-md"
|
|
/>
|
|
{:else if prop.type === 'boolean'}
|
|
<input
|
|
type="checkbox"
|
|
id={key}
|
|
bind:checked={formData[key]}
|
|
class="h-5 w-5"
|
|
/>
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
<button type="submit" class="w-full bg-green-500 text-white p-2 rounded-md hover:bg-green-600">
|
|
Run Task
|
|
</button>
|
|
{/if}
|
|
</form>
|
|
<!-- [/SECTION] -->
|
|
|
|
<!-- [/DEF:DynamicForm:Component] -->
|