Skip to content

Commit 93ba2a6

Browse files
committed
Add TypeScript support for Svelte 4 scaffolds
1 parent 2dc1916 commit 93ba2a6

File tree

16 files changed

+639
-7
lines changed

16 files changed

+639
-7
lines changed

lib/generators/inertia_templates/scaffold/templates/svelte/Form.ts.svelte.tt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
submitText: string
99
}>()
1010

11-
const form = useForm({
12-
<% attributes.each do |attribute| -%>
11+
const form = useForm<<%= inertia_model_form_type %>>({
12+
<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
1313
<% if attribute.password_digest? -%>
1414
password: '',
1515
password_confirmation: '',
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script lang="ts">
2+
import { Link, type InertiaForm } from '@inertiajs/svelte'
3+
import type { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
4+
import Form from './Form.svelte'
5+
6+
export let <%= singular_table_name %>: <%= inertia_model_type %>
7+
8+
const handleSubmit = (e: CustomEvent<{ form: InertiaForm<<%= inertia_model_form_type %>> }>) => {
9+
const { form } = e.detail
10+
form.transform((data) => ({ <%= singular_table_name %>: data }))
11+
<% if attributes.any?(&:attachments?) -%>
12+
form.post(`<%= js_resource_path %>`, {
13+
headers: { 'X-HTTP-METHOD-OVERRIDE': 'put' },
14+
})
15+
<% else -%>
16+
form.patch(`<%= js_resource_path %>`)
17+
<% end -%>
18+
}
19+
</script>
20+
21+
<svelte:head>
22+
<title>Editing <%= human_name.downcase %></title>
23+
</svelte:head>
24+
25+
<h1>Editing <%= human_name.downcase %></h1>
26+
27+
<Form
28+
{<%= singular_table_name %>}
29+
submitText="Update <%= human_name.downcase %>"
30+
on:submit={handleSubmit}
31+
/>
32+
33+
<br />
34+
35+
<div>
36+
<Link href={`<%= js_resource_path %>`}>Show this <%= human_name.downcase %></Link> |
37+
<Link href="<%= js_resources_path %>">Back to <%= human_name.pluralize.downcase %></Link>
38+
</div>

lib/generators/inertia_templates/scaffold/templates/svelte4/Form.svelte.tt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@
5757
type="file"
5858
name="<%= attribute.singular_name %>"
5959
id="<%= attribute.singular_name %>"
60-
oninput={(e) => ($form.<%= attribute.column_name %> = e.target.files[0])}
60+
on:input={(e) => ($form.<%= attribute.column_name %> = e.target.files[0])}
6161
/>
6262
<% elsif attribute.attachments? -%>
6363
<input
6464
type="file"
6565
multiple
6666
name="<%= attribute.singular_name %>[]"
6767
id="<%= attribute.singular_name %>"
68-
oninput={(e) => ($form.<%= attribute.column_name %> = Array.from(e.target.files))}
68+
on:input={(e) => ($form.<%= attribute.column_name %> = Array.from(e.target.files))}
6969
/>
7070
<% else -%>
7171
<input
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<script lang="ts">
2+
import { useForm, type InertiaForm } from '@inertiajs/svelte'
3+
import { createEventDispatcher } from 'svelte'
4+
import type { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
5+
6+
const dispatch = createEventDispatcher<{
7+
submit: { form: InertiaForm<<%= inertia_model_form_type %>> }
8+
}>()
9+
10+
export let <%= singular_table_name %>: <%= inertia_model_type %>
11+
export let submitText: string
12+
13+
<% if attributes.any? { |a| a.attachment? || a.attachments? } -%>
14+
const filesFromEvent = (e: Event) => {
15+
const target = e.target as HTMLInputElement
16+
return Array.from(target.files || [])
17+
}
18+
19+
<% end -%>
20+
const form = useForm<<%= inertia_model_form_type %>>({
21+
<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
22+
<% if attribute.password_digest? -%>
23+
password: '',
24+
password_confirmation: '',
25+
<% else -%>
26+
<%= attribute.column_name %>: <%= singular_table_name %>.<%= attribute.column_name %>,
27+
<% end -%>
28+
<% end -%>
29+
})
30+
</script>
31+
32+
<form on:submit|preventDefault={() => dispatch('submit', { form: $form })}>
33+
<% attributes.each do |attribute| -%>
34+
<% if attribute.password_digest? -%>
35+
<div>
36+
<label for="password">Password</label>
37+
<input
38+
type="password"
39+
name="password"
40+
id="password"
41+
bind:value={$form.password}
42+
/>
43+
{#if $form.errors.password}
44+
<div class="error">{$form.errors.password}</div>
45+
{/if}
46+
</div>
47+
48+
<div>
49+
<label for="password_confirmation">Password Confirmation</label>
50+
<input
51+
type="password"
52+
name="password_confirmation"
53+
id="password_confirmation"
54+
bind:value={$form.password_confirmation}
55+
/>
56+
{#if $form.errors.password_confirmation}
57+
<div class="error">{$form.errors.password_confirmation}</div>
58+
{/if}
59+
</div>
60+
<% else -%>
61+
<div>
62+
<label for="<%= attribute.singular_name %>"><%= attribute.human_name %></label>
63+
<% if input_type(attribute) == "text_area" -%>
64+
<textarea name="<%= attribute.singular_name %>" id="<%= attribute.singular_name %>" bind:value={$form.<%= attribute.column_name %>}></textarea>
65+
<% elsif attribute.attachment? -%>
66+
<input
67+
type="file"
68+
name="<%= attribute.singular_name %>"
69+
id="<%= attribute.singular_name %>"
70+
on:input={(e) => ($form.<%= attribute.column_name %> = filesFromEvent(e)[0])}
71+
/>
72+
<% elsif attribute.attachments? -%>
73+
<input
74+
type="file"
75+
multiple
76+
name="<%= attribute.singular_name %>[]"
77+
id="<%= attribute.singular_name %>"
78+
on:input={(e) => ($form.<%= attribute.column_name %> = filesFromEvent(e))}
79+
/>
80+
<% else -%>
81+
<input
82+
type="<%= input_type(attribute) %>"
83+
name="<%= attribute.singular_name %>"
84+
id="<%= attribute.singular_name %>"
85+
<%= input_type(attribute) == "checkbox" ? "bind:checked" : "bind:value" %>={$form.<%= attribute.column_name %>}
86+
/>
87+
<% end -%>
88+
{#if $form.errors.<%= attribute.column_name %>}
89+
<div class="error">{$form.errors.<%= attribute.column_name %>}</div>
90+
{/if}
91+
</div>
92+
<% end -%>
93+
<% end -%>
94+
<div>
95+
<button type="submit" disabled={$form.processing}>{submitText}</button>
96+
</div>
97+
</form>
98+
99+
<style>
100+
label {
101+
display: block;
102+
}
103+
.error {
104+
color: red;
105+
}
106+
</style>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script lang="ts">
2+
import { Link } from '@inertiajs/svelte'
3+
import <%= inertia_component_name %> from './<%= inertia_component_name %>.svelte'
4+
import type { <%= inertia_model_type %> } from './types'
5+
6+
export let <%= plural_table_name %>: <%= inertia_model_type %>[]
7+
export let flash: { notice?: string }
8+
</script>
9+
10+
<svelte:head>
11+
<title><%= human_name.pluralize %></title>
12+
</svelte:head>
13+
14+
{#if flash.notice}
15+
<p class="notice">{flash.notice}</p>
16+
{/if}
17+
18+
<h1><%= human_name.pluralize %></h1>
19+
20+
<div>
21+
{#each <%= plural_table_name %> as <%= singular_table_name %> (<%= singular_table_name %>.id)}
22+
<div>
23+
<<%= inertia_component_name %> {<%= singular_table_name %>} />
24+
<p>
25+
<Link href={`<%= js_resource_path %>`}>Show this <%= human_name.downcase %></Link>
26+
</p>
27+
</div>
28+
{/each}
29+
</div>
30+
31+
<Link href="<%= js_new_resource_path %>">New <%= human_name.downcase %></Link>
32+
33+
<style>
34+
.notice {
35+
color: green;
36+
}
37+
</style>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script lang="ts">
2+
import { Link, type InertiaForm } from '@inertiajs/svelte'
3+
import Form from './Form.svelte'
4+
import type { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
5+
6+
export let <%= singular_table_name %>: <%= inertia_model_type %>
7+
8+
const handleSubmit = (e: CustomEvent<{ form: InertiaForm<<%= inertia_model_form_type %>> }>) => {
9+
const { form } = e.detail
10+
form.transform((data) => ({ <%= singular_table_name %>: data }))
11+
form.post('<%= js_resources_path %>')
12+
}
13+
</script>
14+
15+
<svelte:head>
16+
<title>New <%= human_name.downcase %></title>
17+
</svelte:head>
18+
19+
<h1>New <%= human_name.downcase %></h1>
20+
21+
<Form
22+
{<%= singular_table_name %>}
23+
submitText="Create <%= human_name.downcase %>"
24+
on:submit={handleSubmit}
25+
/>
26+
27+
<br />
28+
29+
<div>
30+
<Link href="<%= js_resources_path %>">Back to <%= human_name.pluralize.downcase %></Link>
31+
</div>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<script lang="ts">
2+
import type { <%= inertia_model_type %> } from './types'
3+
4+
export let <%= singular_table_name %>: <%= inertia_model_type %>
5+
</script>
6+
7+
<div>
8+
<% attributes.reject(&:password_digest?).each do |attribute| -%>
9+
<p>
10+
<strong><%= attribute.human_name %>:</strong>
11+
<% if attribute.attachment? -%>
12+
{#if <%= singular_table_name %>.<%= attribute.column_name %>}
13+
<a href={<%= singular_table_name %>.<%= attribute.column_name %>.url}>
14+
{<%= singular_table_name %>.<%= attribute.column_name %>.filename}
15+
</a>
16+
{/if}
17+
</p>
18+
<% elsif attribute.attachments? -%>
19+
</p>
20+
{#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }}
21+
<div>
22+
<a href={url}>{filename}</a>
23+
</div>
24+
{/each}
25+
<% else -%>
26+
{<%= singular_table_name %>.<%= attribute.column_name %>}
27+
</p>
28+
<% end -%>
29+
<% end -%>
30+
</div>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script lang="ts">
2+
import { inertia, Link } from '@inertiajs/svelte'
3+
import <%= inertia_component_name %> from './<%= inertia_component_name %>.svelte'
4+
import type { <%= inertia_model_type %> } from './types'
5+
6+
export let <%= singular_table_name %>: <%= inertia_model_type %>
7+
export let flash: { notice?: string }
8+
9+
const onDestroy = (e: MouseEvent) => {
10+
if (!confirm('Are you sure you want to delete this <%= human_name.downcase %>?')) {
11+
e.preventDefault()
12+
}
13+
}
14+
</script>
15+
16+
<svelte:head>
17+
<title><%= human_name %> #{<%= singular_table_name %>.id}</title>
18+
</svelte:head>
19+
20+
{#if flash.notice}
21+
<p class="notice">{flash.notice}</p>
22+
{/if}
23+
24+
<h1><%= human_name %> #{<%= singular_table_name %>.id}</h1>
25+
26+
<<%= inertia_component_name %> {<%= singular_table_name %>} />
27+
28+
<div>
29+
<Link href={`<%= js_edit_resource_path %>`}>Edit this <%= human_name.downcase %></Link> |
30+
<Link href="<%= js_resources_path %>">Back to <%= human_name.pluralize.downcase %></Link>
31+
32+
<br />
33+
34+
<button
35+
use:inertia={{ href: `<%= js_resource_path %>`, method: 'delete' }}
36+
on:click={onDestroy}
37+
type="button"
38+
>
39+
Destroy this <%= human_name.downcase %>
40+
</button>
41+
</div>
42+
43+
<style>
44+
.notice {
45+
color: green;
46+
}
47+
</style>

lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.ts.svelte.tt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
submitText: string
99
}>()
1010

11-
const form = useForm({
12-
<% attributes.each do |attribute| -%>
11+
const form = useForm<<%= inertia_model_form_type %>>({
12+
<% attributes.reject { |a| a.attachment? || a.attachments? }.each do |attribute| -%>
1313
<% if attribute.password_digest? -%>
1414
password: '',
1515
password_confirmation: '',
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<script lang="ts">
2+
import { Link, type InertiaForm } from '@inertiajs/svelte'
3+
import type { <%= inertia_model_type %>, <%= inertia_model_form_type %> } from './types'
4+
import Form from './Form.svelte'
5+
6+
export let <%= singular_table_name %>: <%= inertia_model_type %>
7+
8+
const handleSubmit = (e: CustomEvent<{ form: InertiaForm<<%= inertia_model_form_type %>> }>) => {
9+
const { form } = e.detail
10+
form.transform((data) => ({ <%= singular_table_name %>: data }))
11+
<% if attributes.any?(&:attachments?) -%>
12+
form.post(`<%= js_resource_path %>`, {
13+
headers: { 'X-HTTP-METHOD-OVERRIDE': 'put' },
14+
})
15+
<% else -%>
16+
form.patch(`<%= js_resource_path %>`)
17+
<% end -%>
18+
}
19+
</script>
20+
21+
<svelte:head>
22+
<title>Editing <%= human_name.downcase %></title>
23+
</svelte:head>
24+
25+
<div class="mx-auto md:w-2/3 w-full px-8 pt-8">
26+
<h1 class="font-bold text-4xl">Editing <%= human_name.downcase %></h1>
27+
28+
<Form
29+
{<%= singular_table_name %>}
30+
submitText="Update <%= human_name.downcase %>"
31+
on:submit={handleSubmit}
32+
/>
33+
34+
<Link
35+
href={`<%= js_resource_path %>`}
36+
class="mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
37+
>
38+
Show this <%= human_name.downcase %>
39+
</Link>
40+
<Link
41+
href="<%= js_resources_path %>"
42+
class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium"
43+
>
44+
Back to <%= human_name.pluralize.downcase %>
45+
</Link>
46+
</div>

0 commit comments

Comments
 (0)