inertia_rails 3.13.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/app/views/inertia.html.erb +1 -1
- data/lib/generators/inertia/install/frameworks.yml +3 -18
- data/lib/generators/inertia/install/install_generator.rb +51 -6
- data/lib/generators/inertia/install/templates/assets/rails.svg +9 -0
- data/lib/generators/inertia/install/templates/controller.rb +6 -1
- data/lib/generators/inertia/install/templates/initializer.rb +1 -0
- data/lib/generators/inertia/install/templates/react/InertiaExample.jsx +42 -46
- data/lib/generators/inertia/install/templates/react/InertiaExample.module.css +63 -41
- data/lib/generators/inertia/install/templates/react/InertiaExample.tsx +45 -46
- data/lib/generators/inertia/install/templates/react/inertia.jsx +2 -1
- data/lib/generators/inertia/install/templates/react/inertia.tsx +4 -3
- data/lib/generators/inertia/install/templates/svelte/InertiaExample.svelte +103 -69
- data/lib/generators/inertia/install/templates/svelte/InertiaExample.ts.svelte +104 -69
- data/lib/generators/inertia/install/templates/svelte/inertia.js +1 -1
- data/lib/generators/inertia/install/templates/svelte/inertia.ts +2 -1
- data/lib/generators/inertia/install/templates/vue/InertiaExample.ts.vue +107 -70
- data/lib/generators/inertia/install/templates/vue/InertiaExample.vue +129 -92
- data/lib/generators/inertia/install/templates/vue/inertia.js +3 -3
- data/lib/generators/inertia/install/templates/vue/inertia.ts +4 -3
- data/lib/generators/inertia_templates/scaffold/templates/react/form.tsx.tt +3 -3
- data/lib/generators/inertia_templates/scaffold/templates/svelte/form.ts.svelte.tt +3 -3
- data/lib/generators/inertia_templates/scaffold/templates/svelte/new.svelte.tt +1 -1
- data/lib/generators/inertia_templates/scaffold/templates/svelte/new.ts.svelte.tt +1 -1
- data/lib/generators/inertia_templates/scaffold/templates/vue/form.ts.vue.tt +3 -3
- data/lib/generators/inertia_tw_templates/scaffold/templates/react/form.tsx.tt +3 -3
- data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/form.ts.svelte.tt +3 -3
- data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/new.svelte.tt +1 -2
- data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/new.ts.svelte.tt +1 -1
- data/lib/generators/inertia_tw_templates/scaffold/templates/vue/form.ts.vue.tt +3 -3
- data/lib/inertia_rails/base_prop.rb +1 -1
- data/lib/inertia_rails/configuration.rb +6 -0
- data/lib/inertia_rails/defer_prop.rb +1 -0
- data/lib/inertia_rails/helper.rb +14 -0
- data/lib/inertia_rails/inertia_rails.rb +8 -2
- data/lib/inertia_rails/merge_prop.rb +1 -0
- data/lib/inertia_rails/once_prop.rb +12 -0
- data/lib/inertia_rails/optional_prop.rb +1 -0
- data/lib/inertia_rails/prop_onceable.rb +39 -0
- data/lib/inertia_rails/renderer.rb +52 -13
- data/lib/inertia_rails/version.rb +1 -1
- data/lib/inertia_rails.rb +1 -0
- metadata +5 -2
|
@@ -1,117 +1,154 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Head title="
|
|
2
|
+
<Head title="Ruby on Rails + Inertia + Vue" />
|
|
3
3
|
|
|
4
4
|
<div class="root">
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<a href="https://inertia-rails.dev" target="_blank">
|
|
9
|
-
<img class="logo" :src="inertiaSvg" alt="Inertia logo" />
|
|
5
|
+
<nav class="subNav">
|
|
6
|
+
<a href="https://rubyonrails.org" target="_blank">
|
|
7
|
+
<img class="logo rails" :src="railsSvg" alt="Ruby on Rails Logo" />
|
|
10
8
|
</a>
|
|
11
|
-
<a href="https://
|
|
12
|
-
<img class="logo
|
|
9
|
+
<a href="https://inertia-rails.dev" target="_blank">
|
|
10
|
+
<img class="logo inertia" :src="inertiaSvg" alt="Inertia logo" />
|
|
13
11
|
</a>
|
|
14
12
|
<a href="https://vuejs.org" target="_blank">
|
|
15
|
-
<img class="logo vue" :src="vueSvg" alt="Vue logo"
|
|
13
|
+
<img class="logo vue" :src="vueSvg" alt="Vue logo"/>
|
|
16
14
|
</a>
|
|
17
|
-
</
|
|
15
|
+
</nav>
|
|
18
16
|
|
|
19
|
-
<
|
|
17
|
+
<div class="footer">
|
|
18
|
+
<div class="card">
|
|
19
|
+
<p>
|
|
20
|
+
Edit <code><%= js_destination_path %>/pages/inertia_example/index.vue</code> and save to test <abbr title="Hot Module Replacement">HMR</abbr>.
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
<ul>
|
|
25
|
+
<li>
|
|
26
|
+
<ul>
|
|
27
|
+
<li><strong>Rails version:</strong> {{ rails_version }}</li>
|
|
28
|
+
<li><strong>Rack version:</strong> {{ rack_version }}</li>
|
|
29
|
+
</ul>
|
|
30
|
+
</li>
|
|
31
|
+
<li><strong>Ruby version:</strong> {{ ruby_version }}</li>
|
|
32
|
+
<li>
|
|
33
|
+
<ul>
|
|
34
|
+
<li><strong>Inertia Rails version:</strong> {{ inertia_rails_version }}</li>
|
|
35
|
+
<li><strong>Vue version:</strong> {{ vue_version }}</li>
|
|
36
|
+
</ul>
|
|
37
|
+
</li>
|
|
38
|
+
</ul>
|
|
29
39
|
</div>
|
|
30
|
-
<p class="readTheDocs">
|
|
31
|
-
Click on the Inertia, Vite Ruby, and Vue logos to learn more
|
|
32
|
-
</p>
|
|
33
40
|
</div>
|
|
34
41
|
</template>
|
|
35
42
|
|
|
36
43
|
<script setup>
|
|
37
44
|
import { Head } from '@inertiajs/vue3'
|
|
38
|
-
import {
|
|
45
|
+
import { version as vue_version } from 'vue';
|
|
39
46
|
|
|
47
|
+
import railsSvg from '/assets/rails.svg'
|
|
40
48
|
import inertiaSvg from '/assets/inertia.svg'
|
|
41
|
-
import viteRubySvg from '/assets/vite_ruby.svg'
|
|
42
49
|
import vueSvg from '/assets/vue.svg'
|
|
43
50
|
|
|
44
51
|
defineProps({
|
|
45
|
-
|
|
52
|
+
rails_version: String,
|
|
53
|
+
rack_version: String,
|
|
54
|
+
ruby_version: String,
|
|
55
|
+
inertia_rails_version: String,
|
|
46
56
|
})
|
|
47
|
-
|
|
48
|
-
const count = ref(0)
|
|
49
57
|
</script>
|
|
50
58
|
|
|
59
|
+
<style global>
|
|
60
|
+
body {
|
|
61
|
+
margin: 0;
|
|
62
|
+
padding: 0;
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
65
|
+
|
|
51
66
|
<style scoped>
|
|
52
|
-
.root {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
.logo
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
.
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.
|
|
115
|
-
|
|
116
|
-
|
|
67
|
+
.root {
|
|
68
|
+
box-sizing: border-box;
|
|
69
|
+
margin: 0;
|
|
70
|
+
padding: 0;
|
|
71
|
+
align-items: center;
|
|
72
|
+
background-color: #F0E7E9;
|
|
73
|
+
background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEwMjQiIHZpZXdCb3g9IjAgMCAxNDQwIDEwMjQiIHdpZHRoPSIxNDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Im0xNDQwIDUxMC4wMDA2NDh2LTUxMC4wMDA2NDhoLTE0NDB2Mzg0LjAwMDY0OGM0MTcuMzExOTM5IDEzMS4xNDIxNzkgODkxIDE3MS41MTMgMTQ0MCAxMjZ6IiBmaWxsPSIjZmZmIi8+PC9zdmc+);
|
|
74
|
+
background-position: center center;
|
|
75
|
+
background-repeat: no-repeat;
|
|
76
|
+
background-size: cover;
|
|
77
|
+
color: #261B23;
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
font-family: Sans-Serif;
|
|
81
|
+
font-size: calc(0.9em + 0.5vw);
|
|
82
|
+
font-style: normal;
|
|
83
|
+
font-weight: 400;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
line-height: 1.25;
|
|
86
|
+
min-height: 100vh;
|
|
87
|
+
text-align: center;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@media (prefers-color-scheme: dark) {
|
|
91
|
+
.root {
|
|
92
|
+
background-color: #1a1a1a;
|
|
93
|
+
background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEwMjQiIHZpZXdCb3g9IjAgMCAxNDQwIDEwMjQiIHdpZHRoPSIxNDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Im0xNDQwIDUxMC4wMDA2NDh2LTUxMC4wMDA2NDhoLTE0NDB2Mzg0LjAwMDY0OGM0MTcuMzExOTM5IDEzMS4xNDIxNzkgODkxIDE3MS41MTMgMTQ0MCAxMjZ6IiBmaWxsPSIjMzMzIi8+PC9zdmc+);
|
|
94
|
+
color: #e0e0e0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.logo {
|
|
99
|
+
display: inline-block;
|
|
100
|
+
height: 9.8vw;
|
|
101
|
+
min-height: 130px;
|
|
102
|
+
padding: 1.5em;
|
|
103
|
+
will-change: filter;
|
|
104
|
+
transition: filter 300ms;
|
|
105
|
+
filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
|
|
106
|
+
}
|
|
107
|
+
.logo.inertia:hover {
|
|
108
|
+
filter: drop-shadow(0 0 2em #646cffaa);
|
|
109
|
+
}
|
|
110
|
+
.logo.vue:hover {
|
|
111
|
+
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
112
|
+
}
|
|
113
|
+
.logo.rails:hover {
|
|
114
|
+
filter: drop-shadow(0 0 2em rgb(211 0 1 / 0.6));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@media (prefers-color-scheme: dark) {
|
|
118
|
+
.logo {
|
|
119
|
+
filter: drop-shadow(0 20px 13px rgb(255 255 255 / 0.03)) drop-shadow(0 8px 5px rgb(255 255 255 / 0.08));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.card {
|
|
124
|
+
padding: 2em;
|
|
125
|
+
font-size: 0.7em;
|
|
126
|
+
color: #948e90;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.footer {
|
|
130
|
+
bottom: 0;
|
|
131
|
+
left: 0;
|
|
132
|
+
margin: 0 2rem 2rem 2rem;
|
|
133
|
+
position: absolute;
|
|
134
|
+
right: 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.footer ul {
|
|
138
|
+
list-style: none;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.footer ul li {
|
|
142
|
+
display: inline;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.footer ul ul li:after {
|
|
146
|
+
content: " | ";
|
|
147
|
+
font-weight: 300;
|
|
148
|
+
color: #948e90;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.footer ul ul li:last-child:after {
|
|
152
|
+
content: "";
|
|
153
|
+
}
|
|
117
154
|
</style>
|
|
@@ -37,14 +37,14 @@ createInertiaApp({
|
|
|
37
37
|
},
|
|
38
38
|
|
|
39
39
|
defaults: {
|
|
40
|
+
form: {
|
|
41
|
+
forceIndicesArrayFormatInFormData: false,
|
|
42
|
+
},
|
|
40
43
|
future: {
|
|
41
44
|
useDataInertiaHeadAttribute: true,
|
|
42
45
|
useDialogForErrorModal: true,
|
|
43
46
|
preserveEqualProps: true,
|
|
44
47
|
},
|
|
45
|
-
visitOptions: () => {
|
|
46
|
-
return { queryStringArrayFormat: "brackets" }
|
|
47
|
-
},
|
|
48
48
|
},
|
|
49
49
|
}).catch((error) => {
|
|
50
50
|
// This ensures this entrypoint is only loaded on Inertia pages
|
|
@@ -37,14 +37,15 @@ createInertiaApp({
|
|
|
37
37
|
},
|
|
38
38
|
|
|
39
39
|
defaults: {
|
|
40
|
+
form: {
|
|
41
|
+
forceIndicesArrayFormatInFormData: false,
|
|
42
|
+
},
|
|
40
43
|
future: {
|
|
44
|
+
useScriptElementForInitialPage: true,
|
|
41
45
|
useDataInertiaHeadAttribute: true,
|
|
42
46
|
useDialogForErrorModal: true,
|
|
43
47
|
preserveEqualProps: true,
|
|
44
48
|
},
|
|
45
|
-
visitOptions: () => {
|
|
46
|
-
return { queryStringArrayFormat: "brackets" }
|
|
47
|
-
},
|
|
48
49
|
},
|
|
49
50
|
}).catch((error) => {
|
|
50
51
|
// This ensures this entrypoint is only loaded on Inertia pages
|
|
@@ -28,7 +28,7 @@ export default function Form({ <%= singular_table_name %>, submitText, ...formPr
|
|
|
28
28
|
id="password"
|
|
29
29
|
/>
|
|
30
30
|
{errors.password && (
|
|
31
|
-
<div style={{ color: 'red' }}>{errors.password}</div>
|
|
31
|
+
<div style={{ color: 'red' }}>{errors.password.join(', ')}</div>
|
|
32
32
|
)}
|
|
33
33
|
</div>
|
|
34
34
|
|
|
@@ -42,7 +42,7 @@ export default function Form({ <%= singular_table_name %>, submitText, ...formPr
|
|
|
42
42
|
id="password_confirmation"
|
|
43
43
|
/>
|
|
44
44
|
{errors.password_confirmation && (
|
|
45
|
-
<div style={{ color: 'red' }}>{errors.password_confirmation}</div>
|
|
45
|
+
<div style={{ color: 'red' }}>{errors.password_confirmation.join(', ')}</div>
|
|
46
46
|
)}
|
|
47
47
|
</div>
|
|
48
48
|
<% else -%>
|
|
@@ -92,7 +92,7 @@ export default function Form({ <%= singular_table_name %>, submitText, ...formPr
|
|
|
92
92
|
/>
|
|
93
93
|
<% end -%>
|
|
94
94
|
{errors.<%= attribute.column_name %> && (
|
|
95
|
-
<div style={{ color: 'red' }}>{errors.<%= attribute.column_name
|
|
95
|
+
<div style={{ color: 'red' }}>{errors.<%= attribute.column_name %>.join(', ')}</div>
|
|
96
96
|
)}
|
|
97
97
|
</div>
|
|
98
98
|
<% end -%>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
id="password"
|
|
30
30
|
/>
|
|
31
31
|
{#if errors.password}
|
|
32
|
-
<div class="error">{errors.password}</div>
|
|
32
|
+
<div class="error">{errors.password.join(', ')}</div>
|
|
33
33
|
{/if}
|
|
34
34
|
</div>
|
|
35
35
|
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
id="password_confirmation"
|
|
42
42
|
/>
|
|
43
43
|
{#if errors.password_confirmation}
|
|
44
|
-
<div class="error">{errors.password_confirmation}</div>
|
|
44
|
+
<div class="error">{errors.password_confirmation.join(', ')}</div>
|
|
45
45
|
{/if}
|
|
46
46
|
</div>
|
|
47
47
|
<% else -%>
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
/>
|
|
83
83
|
<% end -%>
|
|
84
84
|
{#if errors.<%= attribute.column_name %>}
|
|
85
|
-
<div class="error">{errors.<%= attribute.column_name
|
|
85
|
+
<div class="error">{errors.<%= attribute.column_name %>.join(', ')}</div>
|
|
86
86
|
{/if}
|
|
87
87
|
</div>
|
|
88
88
|
<% end -%>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
id="password"
|
|
15
15
|
/>
|
|
16
16
|
<div v-if="errors.password" class="error">
|
|
17
|
-
{{ errors.password }}
|
|
17
|
+
{{ errors.password.join(', ') }}
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
20
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
id="password_confirmation"
|
|
29
29
|
/>
|
|
30
30
|
<div v-if="errors.password_confirmation" class="error">
|
|
31
|
-
{{ errors.password_confirmation }}
|
|
31
|
+
{{ errors.password_confirmation.join(', ') }}
|
|
32
32
|
</div>
|
|
33
33
|
</div>
|
|
34
34
|
<% else -%>
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
/>
|
|
70
70
|
<% end -%>
|
|
71
71
|
<div v-if="errors.<%= attribute.column_name %>" class="error">
|
|
72
|
-
{{ errors.<%= attribute.column_name
|
|
72
|
+
{{ errors.<%= attribute.column_name %>.join(', ') }}
|
|
73
73
|
</div>
|
|
74
74
|
</div>
|
|
75
75
|
<% end -%>
|
|
@@ -29,7 +29,7 @@ export default function Form({ <%= singular_table_name %>, submitText, ...formPr
|
|
|
29
29
|
/>
|
|
30
30
|
{errors.password && (
|
|
31
31
|
<div className="text-red-500 px-3 py-2 font-medium">
|
|
32
|
-
{errors.password}
|
|
32
|
+
{errors.password.join(', ')}
|
|
33
33
|
</div>
|
|
34
34
|
)}
|
|
35
35
|
</div>
|
|
@@ -44,7 +44,7 @@ export default function Form({ <%= singular_table_name %>, submitText, ...formPr
|
|
|
44
44
|
/>
|
|
45
45
|
{errors.password_confirmation && (
|
|
46
46
|
<div className="text-red-500 px-3 py-2 font-medium">
|
|
47
|
-
{errors.password_confirmation}
|
|
47
|
+
{errors.password_confirmation.join(', ')}
|
|
48
48
|
</div>
|
|
49
49
|
)}
|
|
50
50
|
<% else -%>
|
|
@@ -99,7 +99,7 @@ export default function Form({ <%= singular_table_name %>, submitText, ...formPr
|
|
|
99
99
|
<% end -%>
|
|
100
100
|
{errors.<%= attribute.column_name %> && (
|
|
101
101
|
<div className="text-red-500 px-3 py-2 font-medium">
|
|
102
|
-
{errors.<%= attribute.column_name
|
|
102
|
+
{errors.<%= attribute.column_name %>.join(', ')}
|
|
103
103
|
</div>
|
|
104
104
|
)}
|
|
105
105
|
<% end -%>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
/>
|
|
32
32
|
{#if errors.password}
|
|
33
33
|
<div class="text-red-500 px-3 py-2 font-medium">
|
|
34
|
-
{errors.password}
|
|
34
|
+
{errors.password.join(', ')}
|
|
35
35
|
</div>
|
|
36
36
|
{/if}
|
|
37
37
|
</div>
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
/>
|
|
47
47
|
{#if errors.password_confirmation}
|
|
48
48
|
<div class="text-red-500 px-3 py-2 font-medium">
|
|
49
|
-
{errors.password_confirmation}
|
|
49
|
+
{errors.password_confirmation.join(', ')}
|
|
50
50
|
</div>
|
|
51
51
|
{/if}
|
|
52
52
|
</div>
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
<% end -%>
|
|
96
96
|
{#if errors.<%= attribute.column_name %>}
|
|
97
97
|
<div class="text-red-500 px-3 py-2 font-medium">
|
|
98
|
-
{errors.<%= attribute.column_name
|
|
98
|
+
{errors.<%= attribute.column_name %>.join(', ')}
|
|
99
99
|
</div>
|
|
100
100
|
{/if}
|
|
101
101
|
</div>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
v-if="errors.password"
|
|
20
20
|
class="text-red-500 px-3 py-2 font-medium"
|
|
21
21
|
>
|
|
22
|
-
{{ errors.password }}
|
|
22
|
+
{{ errors.password.join(', ') }}
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
v-if="errors.password_confirmation"
|
|
36
36
|
class="text-red-500 px-3 py-2 font-medium"
|
|
37
37
|
>
|
|
38
|
-
{{ errors.password_confirmation }}
|
|
38
|
+
{{ errors.password_confirmation.join(', ') }}
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
41
41
|
<% else -%>
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
/>
|
|
83
83
|
<% end -%>
|
|
84
84
|
<div v-if="errors.<%= attribute.column_name %>" class="text-red-500 px-3 py-2 font-medium">
|
|
85
|
-
{{ errors.<%= attribute.column_name
|
|
85
|
+
{{ errors.<%= attribute.column_name %>.join(', ') }}
|
|
86
86
|
</div>
|
|
87
87
|
</div>
|
|
88
88
|
<% end -%>
|
|
@@ -34,6 +34,12 @@ module InertiaRails
|
|
|
34
34
|
|
|
35
35
|
# Whether to include empty `errors` hash to the props when no errors are present.
|
|
36
36
|
always_include_errors_hash: nil,
|
|
37
|
+
|
|
38
|
+
# Whether to use `<script>` element for initial page rendering instead of the `data-page` attribute.
|
|
39
|
+
use_script_element_for_initial_page: false,
|
|
40
|
+
|
|
41
|
+
# DOM id to use for the root Inertia.js element.
|
|
42
|
+
root_dom_id: 'app',
|
|
37
43
|
}.freeze
|
|
38
44
|
|
|
39
45
|
OPTION_NAMES = DEFAULTS.keys.freeze
|
data/lib/inertia_rails/helper.rb
CHANGED
|
@@ -32,5 +32,19 @@ module InertiaRails
|
|
|
32
32
|
|
|
33
33
|
safe_join(meta_tags, "\n")
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
def inertia_root(id: nil, page: inertia_page)
|
|
37
|
+
config = controller.send(:inertia_configuration)
|
|
38
|
+
id ||= config.root_dom_id
|
|
39
|
+
|
|
40
|
+
if config.use_script_element_for_initial_page
|
|
41
|
+
safe_join([
|
|
42
|
+
tag.script(page.to_json.html_safe, 'data-page': id, type: 'application/json'),
|
|
43
|
+
tag.div(id: id)
|
|
44
|
+
], "\n")
|
|
45
|
+
else
|
|
46
|
+
tag.div(id: id, 'data-page': page.to_json)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
35
49
|
end
|
|
36
50
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'inertia_rails/prop_onceable'
|
|
3
4
|
require 'inertia_rails/prop_mergeable'
|
|
4
5
|
require 'inertia_rails/base_prop'
|
|
5
6
|
require 'inertia_rails/ignore_on_first_load_prop'
|
|
@@ -8,6 +9,7 @@ require 'inertia_rails/lazy_prop'
|
|
|
8
9
|
require 'inertia_rails/optional_prop'
|
|
9
10
|
require 'inertia_rails/defer_prop'
|
|
10
11
|
require 'inertia_rails/merge_prop'
|
|
12
|
+
require 'inertia_rails/once_prop'
|
|
11
13
|
require 'inertia_rails/scroll_prop'
|
|
12
14
|
require 'inertia_rails/configuration'
|
|
13
15
|
require 'inertia_rails/meta_tag'
|
|
@@ -36,6 +38,10 @@ module InertiaRails
|
|
|
36
38
|
AlwaysProp.new(&block)
|
|
37
39
|
end
|
|
38
40
|
|
|
41
|
+
def once(...)
|
|
42
|
+
OnceProp.new(...)
|
|
43
|
+
end
|
|
44
|
+
|
|
39
45
|
def merge(...)
|
|
40
46
|
MergeProp.new(...)
|
|
41
47
|
end
|
|
@@ -44,8 +50,8 @@ module InertiaRails
|
|
|
44
50
|
MergeProp.new(deep_merge: true, match_on: match_on, &block)
|
|
45
51
|
end
|
|
46
52
|
|
|
47
|
-
def defer(
|
|
48
|
-
DeferProp.new(
|
|
53
|
+
def defer(...)
|
|
54
|
+
DeferProp.new(...)
|
|
49
55
|
end
|
|
50
56
|
|
|
51
57
|
def scroll(metadata = nil, **options, &block)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module InertiaRails
|
|
4
|
+
module PropOnceable
|
|
5
|
+
attr_reader :once_key, :once_expires_in
|
|
6
|
+
|
|
7
|
+
def initialize(**props, &block)
|
|
8
|
+
@once = props.fetch(:once, false)
|
|
9
|
+
@once_key = props[:key]
|
|
10
|
+
@once_expires_in = props[:expires_in]
|
|
11
|
+
@fresh = props.fetch(:fresh, false)
|
|
12
|
+
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def once?
|
|
17
|
+
@once
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def fresh?
|
|
21
|
+
@fresh
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def expires_at
|
|
25
|
+
return nil unless @once_expires_in
|
|
26
|
+
|
|
27
|
+
timestamp = case @once_expires_in
|
|
28
|
+
when ActiveSupport::Duration
|
|
29
|
+
(Time.current + @once_expires_in).to_f
|
|
30
|
+
when Numeric
|
|
31
|
+
Time.current.to_f + @once_expires_in
|
|
32
|
+
else
|
|
33
|
+
raise ArgumentError, "Invalid `expires_in` value: #{@once_expires_in.inspect}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
(timestamp * 1000).to_i
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|