@inertiajs/vue3 2.3.15 → 2.3.17
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inertiajs/vue3",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.17",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The Vue 3 adapter for Inertia.js",
|
|
6
6
|
"contributors": [
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist",
|
|
20
|
-
"types"
|
|
20
|
+
"types",
|
|
21
|
+
"resources"
|
|
21
22
|
],
|
|
22
23
|
"type": "module",
|
|
23
24
|
"main": "dist/index.js",
|
|
@@ -43,11 +44,11 @@
|
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"axios": "^1.13.5",
|
|
46
|
-
"es-check": "^9.
|
|
47
|
+
"es-check": "^9.6.1",
|
|
47
48
|
"esbuild": "^0.27.3",
|
|
48
49
|
"esbuild-node-externals": "^1.20.1",
|
|
49
50
|
"typescript": "^5.9.3",
|
|
50
|
-
"vue": "^3.5.
|
|
51
|
+
"vue": "^3.5.29"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
54
|
"vue": "^3.0.0"
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"@types/lodash-es": "^4.17.12",
|
|
57
58
|
"laravel-precognition": "^1.0.2",
|
|
58
59
|
"lodash-es": "^4.17.23",
|
|
59
|
-
"@inertiajs/core": "2.3.
|
|
60
|
+
"@inertiajs/core": "2.3.17"
|
|
60
61
|
},
|
|
61
62
|
"scripts": {
|
|
62
63
|
"build": "pnpm clean && ./build.js && tsc",
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: inertia-vue-development
|
|
3
|
+
description: "Develops Inertia.js v2 Vue client-side applications. Activates when creating Vue pages, forms, or navigation; using <Link>, <Form>, useForm, or router; working with deferred props, prefetching, or polling; or when user mentions Vue with Inertia, Vue pages, Vue forms, or Vue navigation."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: laravel
|
|
7
|
+
---
|
|
8
|
+
@php
|
|
9
|
+
/** @var \Laravel\Boost\Install\GuidelineAssist $assist */
|
|
10
|
+
@endphp
|
|
11
|
+
# Inertia Vue Development
|
|
12
|
+
|
|
13
|
+
## When to Apply
|
|
14
|
+
|
|
15
|
+
Activate this skill when:
|
|
16
|
+
|
|
17
|
+
- Creating or modifying Vue page components for Inertia
|
|
18
|
+
- Working with forms in Vue (using `<Form>` or `useForm`)
|
|
19
|
+
- Implementing client-side navigation with `<Link>` or `router`
|
|
20
|
+
- Using v2 features: deferred props, prefetching, WhenVisible, InfiniteScroll, once props, flash data, or polling
|
|
21
|
+
- Building Vue-specific features with the Inertia protocol
|
|
22
|
+
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
Use `search-docs` for detailed Inertia v2 Vue patterns and documentation.
|
|
26
|
+
|
|
27
|
+
## Basic Usage
|
|
28
|
+
|
|
29
|
+
### Page Components Location
|
|
30
|
+
|
|
31
|
+
Vue page components should be placed in the `{{ $assist->inertia()->pagesDirectory() }}` directory.
|
|
32
|
+
|
|
33
|
+
### Page Component Structure
|
|
34
|
+
|
|
35
|
+
@verbatim
|
|
36
|
+
@boostsnippet("Basic Vue Page Component", "vue")
|
|
37
|
+
<script setup>
|
|
38
|
+
defineProps({
|
|
39
|
+
users: Array
|
|
40
|
+
})
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<div>
|
|
45
|
+
<h1>Users</h1>
|
|
46
|
+
<ul>
|
|
47
|
+
<li v-for="user in users" :key="user.id">
|
|
48
|
+
{{ user.name }}
|
|
49
|
+
</li>
|
|
50
|
+
</ul>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
@endboostsnippet
|
|
54
|
+
@endverbatim
|
|
55
|
+
|
|
56
|
+
## Client-Side Navigation
|
|
57
|
+
|
|
58
|
+
### Basic Link Component
|
|
59
|
+
|
|
60
|
+
Use `<Link>` for client-side navigation instead of traditional `<a>` tags:
|
|
61
|
+
|
|
62
|
+
@boostsnippet("Inertia Vue Navigation", "vue")
|
|
63
|
+
<script setup>
|
|
64
|
+
import { Link } from '@inertiajs/vue3'
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<div>
|
|
69
|
+
<Link href="/">Home</Link>
|
|
70
|
+
<Link href="/users">Users</Link>
|
|
71
|
+
<Link :href="`/users/${user.id}`">View User</Link>
|
|
72
|
+
</div>
|
|
73
|
+
</template>
|
|
74
|
+
@endboostsnippet
|
|
75
|
+
|
|
76
|
+
### Link with Method
|
|
77
|
+
|
|
78
|
+
@boostsnippet("Link with POST Method", "vue")
|
|
79
|
+
<script setup>
|
|
80
|
+
import { Link } from '@inertiajs/vue3'
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<template>
|
|
84
|
+
<Link href="/logout" method="post" as="button">
|
|
85
|
+
Logout
|
|
86
|
+
</Link>
|
|
87
|
+
</template>
|
|
88
|
+
@endboostsnippet
|
|
89
|
+
|
|
90
|
+
### Prefetching
|
|
91
|
+
|
|
92
|
+
Prefetch pages to improve perceived performance:
|
|
93
|
+
|
|
94
|
+
@boostsnippet("Prefetch on Hover", "vue")
|
|
95
|
+
<script setup>
|
|
96
|
+
import { Link } from '@inertiajs/vue3'
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<template>
|
|
100
|
+
<Link href="/users" prefetch>
|
|
101
|
+
Users
|
|
102
|
+
</Link>
|
|
103
|
+
</template>
|
|
104
|
+
@endboostsnippet
|
|
105
|
+
|
|
106
|
+
### Programmatic Navigation
|
|
107
|
+
|
|
108
|
+
@boostsnippet("Router Visit", "vue")
|
|
109
|
+
<script setup>
|
|
110
|
+
import { router } from '@inertiajs/vue3'
|
|
111
|
+
|
|
112
|
+
function handleClick() {
|
|
113
|
+
router.visit('/users')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Or with options
|
|
117
|
+
function createUser() {
|
|
118
|
+
router.visit('/users', {
|
|
119
|
+
method: 'post',
|
|
120
|
+
data: { name: 'John' },
|
|
121
|
+
onSuccess: () => console.log('Done'),
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
</script>
|
|
125
|
+
|
|
126
|
+
<template>
|
|
127
|
+
<Link href="/users">Users</Link>
|
|
128
|
+
<Link href="/logout" method="post" as="button">Logout</Link>
|
|
129
|
+
</template>
|
|
130
|
+
@endboostsnippet
|
|
131
|
+
|
|
132
|
+
## Form Handling
|
|
133
|
+
|
|
134
|
+
@if($assist->inertia()->hasFormComponent())
|
|
135
|
+
### Form Component (Recommended)
|
|
136
|
+
|
|
137
|
+
The recommended way to build forms is with the `<Form>` component:
|
|
138
|
+
|
|
139
|
+
@verbatim
|
|
140
|
+
@boostsnippet("Form Component Example", "vue")
|
|
141
|
+
<script setup>
|
|
142
|
+
import { Form } from '@inertiajs/vue3'
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<template>
|
|
146
|
+
<Form action="/users" method="post" #default="{ errors, processing, wasSuccessful }">
|
|
147
|
+
<input type="text" name="name" />
|
|
148
|
+
<div v-if="errors.name">{{ errors.name }}</div>
|
|
149
|
+
|
|
150
|
+
<input type="email" name="email" />
|
|
151
|
+
<div v-if="errors.email">{{ errors.email }}</div>
|
|
152
|
+
|
|
153
|
+
<button type="submit" :disabled="processing">
|
|
154
|
+
{{ processing ? 'Creating...' : 'Create User' }}
|
|
155
|
+
</button>
|
|
156
|
+
|
|
157
|
+
<div v-if="wasSuccessful">User created!</div>
|
|
158
|
+
</Form>
|
|
159
|
+
</template>
|
|
160
|
+
@endboostsnippet
|
|
161
|
+
@endverbatim
|
|
162
|
+
|
|
163
|
+
### Form Component With All Props
|
|
164
|
+
|
|
165
|
+
@verbatim
|
|
166
|
+
@boostsnippet("Form Component Full Example", "vue")
|
|
167
|
+
<script setup>
|
|
168
|
+
import { Form } from '@inertiajs/vue3'
|
|
169
|
+
</script>
|
|
170
|
+
|
|
171
|
+
<template>
|
|
172
|
+
<Form
|
|
173
|
+
action="/users"
|
|
174
|
+
method="post"
|
|
175
|
+
#default="{
|
|
176
|
+
errors,
|
|
177
|
+
hasErrors,
|
|
178
|
+
processing,
|
|
179
|
+
progress,
|
|
180
|
+
wasSuccessful,
|
|
181
|
+
recentlySuccessful,
|
|
182
|
+
setError,
|
|
183
|
+
clearErrors,
|
|
184
|
+
resetAndClearErrors,
|
|
185
|
+
defaults,
|
|
186
|
+
isDirty,
|
|
187
|
+
reset,
|
|
188
|
+
submit
|
|
189
|
+
}"
|
|
190
|
+
>
|
|
191
|
+
<input type="text" name="name" :value="defaults.name" />
|
|
192
|
+
<div v-if="errors.name">{{ errors.name }}</div>
|
|
193
|
+
|
|
194
|
+
<button type="submit" :disabled="processing">
|
|
195
|
+
{{ processing ? 'Saving...' : 'Save' }}
|
|
196
|
+
</button>
|
|
197
|
+
|
|
198
|
+
<progress v-if="progress" :value="progress.percentage" max="100">
|
|
199
|
+
{{ progress.percentage }}%
|
|
200
|
+
</progress>
|
|
201
|
+
|
|
202
|
+
<div v-if="wasSuccessful">Saved!</div>
|
|
203
|
+
</Form>
|
|
204
|
+
</template>
|
|
205
|
+
@endboostsnippet
|
|
206
|
+
@endverbatim
|
|
207
|
+
|
|
208
|
+
@if($assist->inertia()->hasFormComponentResets())
|
|
209
|
+
### Form Component Reset Props
|
|
210
|
+
|
|
211
|
+
The `<Form>` component supports automatic resetting:
|
|
212
|
+
|
|
213
|
+
- `resetOnError` - Reset form data when the request fails
|
|
214
|
+
- `resetOnSuccess` - Reset form data when the request succeeds
|
|
215
|
+
- `setDefaultsOnSuccess` - Update default values on success
|
|
216
|
+
|
|
217
|
+
Use the `search-docs` tool with a query of `form component resetting` for detailed guidance.
|
|
218
|
+
|
|
219
|
+
@verbatim
|
|
220
|
+
@boostsnippet("Form with Reset Props", "vue")
|
|
221
|
+
<script setup>
|
|
222
|
+
import { Form } from '@inertiajs/vue3'
|
|
223
|
+
</script>
|
|
224
|
+
|
|
225
|
+
<template>
|
|
226
|
+
<Form
|
|
227
|
+
action="/users"
|
|
228
|
+
method="post"
|
|
229
|
+
reset-on-success
|
|
230
|
+
set-defaults-on-success
|
|
231
|
+
#default="{ errors, processing, wasSuccessful }"
|
|
232
|
+
>
|
|
233
|
+
<input type="text" name="name" />
|
|
234
|
+
<div v-if="errors.name">{{ errors.name }}</div>
|
|
235
|
+
|
|
236
|
+
<button type="submit" :disabled="processing">
|
|
237
|
+
Submit
|
|
238
|
+
</button>
|
|
239
|
+
</Form>
|
|
240
|
+
</template>
|
|
241
|
+
@endboostsnippet
|
|
242
|
+
@endverbatim
|
|
243
|
+
@else
|
|
244
|
+
Note: This version of Inertia does not support `resetOnError`, `resetOnSuccess`, or `setDefaultsOnSuccess` on the `<Form>` component. Using these props will cause errors. Upgrade to Inertia v2.2.0+ to use these features.
|
|
245
|
+
@endif
|
|
246
|
+
|
|
247
|
+
Forms can also be built using the `useForm` composable for more programmatic control. Use the `search-docs` tool with a query of `useForm helper` for guidance.
|
|
248
|
+
|
|
249
|
+
@endif
|
|
250
|
+
|
|
251
|
+
### `useForm` Composable
|
|
252
|
+
|
|
253
|
+
@if($assist->inertia()->hasFormComponent() === false)
|
|
254
|
+
For Inertia v2.0.x: Build forms using the `useForm` composable as the `<Form>` component is not available until v2.1.0+.
|
|
255
|
+
@else
|
|
256
|
+
For more programmatic control or to follow existing conventions, use the `useForm` composable:
|
|
257
|
+
@endif
|
|
258
|
+
|
|
259
|
+
@verbatim
|
|
260
|
+
@boostsnippet("useForm Composable Example", "vue")
|
|
261
|
+
<script setup>
|
|
262
|
+
import { useForm } from '@inertiajs/vue3'
|
|
263
|
+
|
|
264
|
+
const form = useForm({
|
|
265
|
+
name: '',
|
|
266
|
+
email: '',
|
|
267
|
+
password: '',
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
function submit() {
|
|
271
|
+
form.post('/users', {
|
|
272
|
+
onSuccess: () => form.reset('password'),
|
|
273
|
+
})
|
|
274
|
+
}
|
|
275
|
+
</script>
|
|
276
|
+
|
|
277
|
+
<template>
|
|
278
|
+
<form @submit.prevent="submit">
|
|
279
|
+
<input type="text" v-model="form.name" />
|
|
280
|
+
<div v-if="form.errors.name">{{ form.errors.name }}</div>
|
|
281
|
+
|
|
282
|
+
<input type="email" v-model="form.email" />
|
|
283
|
+
<div v-if="form.errors.email">{{ form.errors.email }}</div>
|
|
284
|
+
|
|
285
|
+
<input type="password" v-model="form.password" />
|
|
286
|
+
<div v-if="form.errors.password">{{ form.errors.password }}</div>
|
|
287
|
+
|
|
288
|
+
<button type="submit" :disabled="form.processing">
|
|
289
|
+
Create User
|
|
290
|
+
</button>
|
|
291
|
+
</form>
|
|
292
|
+
</template>
|
|
293
|
+
@endboostsnippet
|
|
294
|
+
@endverbatim
|
|
295
|
+
|
|
296
|
+
## Inertia v2 Features
|
|
297
|
+
|
|
298
|
+
### Deferred Props
|
|
299
|
+
|
|
300
|
+
Use deferred props to load data after initial page render:
|
|
301
|
+
|
|
302
|
+
@verbatim
|
|
303
|
+
@boostsnippet("Deferred Props with Empty State", "vue")
|
|
304
|
+
<script setup>
|
|
305
|
+
defineProps({
|
|
306
|
+
users: Array
|
|
307
|
+
})
|
|
308
|
+
</script>
|
|
309
|
+
|
|
310
|
+
<template>
|
|
311
|
+
<div>
|
|
312
|
+
<h1>Users</h1>
|
|
313
|
+
<div v-if="!users" class="animate-pulse">
|
|
314
|
+
<div class="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
|
|
315
|
+
<div class="h-4 bg-gray-200 rounded w-1/2"></div>
|
|
316
|
+
</div>
|
|
317
|
+
<ul v-else>
|
|
318
|
+
<li v-for="user in users" :key="user.id">
|
|
319
|
+
{{ user.name }}
|
|
320
|
+
</li>
|
|
321
|
+
</ul>
|
|
322
|
+
</div>
|
|
323
|
+
</template>
|
|
324
|
+
@endboostsnippet
|
|
325
|
+
@endverbatim
|
|
326
|
+
|
|
327
|
+
### Polling
|
|
328
|
+
|
|
329
|
+
Automatically refresh data at intervals:
|
|
330
|
+
|
|
331
|
+
@verbatim
|
|
332
|
+
@boostsnippet("Polling Example", "vue")
|
|
333
|
+
<script setup>
|
|
334
|
+
import { router } from '@inertiajs/vue3'
|
|
335
|
+
import { onMounted, onUnmounted } from 'vue'
|
|
336
|
+
|
|
337
|
+
defineProps({
|
|
338
|
+
stats: Object
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
let interval
|
|
342
|
+
|
|
343
|
+
onMounted(() => {
|
|
344
|
+
interval = setInterval(() => {
|
|
345
|
+
router.reload({ only: ['stats'] })
|
|
346
|
+
}, 5000) // Poll every 5 seconds
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
onUnmounted(() => {
|
|
350
|
+
clearInterval(interval)
|
|
351
|
+
})
|
|
352
|
+
</script>
|
|
353
|
+
|
|
354
|
+
<template>
|
|
355
|
+
<div>
|
|
356
|
+
<h1>Dashboard</h1>
|
|
357
|
+
<div>Active Users: {{ stats.activeUsers }}</div>
|
|
358
|
+
</div>
|
|
359
|
+
</template>
|
|
360
|
+
@endboostsnippet
|
|
361
|
+
@endverbatim
|
|
362
|
+
|
|
363
|
+
### WhenVisible
|
|
364
|
+
|
|
365
|
+
Lazy-load a prop when an element scrolls into view. Useful for deferring expensive data that sits below the fold:
|
|
366
|
+
|
|
367
|
+
@verbatim
|
|
368
|
+
@boostsnippet("WhenVisible Example", "vue")
|
|
369
|
+
<script setup>
|
|
370
|
+
import { WhenVisible } from '@inertiajs/vue3'
|
|
371
|
+
|
|
372
|
+
defineProps({
|
|
373
|
+
stats: Object
|
|
374
|
+
})
|
|
375
|
+
</script>
|
|
376
|
+
|
|
377
|
+
<template>
|
|
378
|
+
<div>
|
|
379
|
+
<h1>Dashboard</h1>
|
|
380
|
+
|
|
381
|
+
<!-- stats prop is loaded only when this section scrolls into view -->
|
|
382
|
+
<WhenVisible data="stats" :buffer="200">
|
|
383
|
+
<template #fallback>
|
|
384
|
+
<div class="animate-pulse">Loading stats...</div>
|
|
385
|
+
</template>
|
|
386
|
+
|
|
387
|
+
<template #default="{ fetching }">
|
|
388
|
+
<div>
|
|
389
|
+
<p>Total Users: {{ stats.total_users }}</p>
|
|
390
|
+
<p>Revenue: {{ stats.revenue }}</p>
|
|
391
|
+
<span v-if="fetching">Refreshing...</span>
|
|
392
|
+
</div>
|
|
393
|
+
</template>
|
|
394
|
+
</WhenVisible>
|
|
395
|
+
</div>
|
|
396
|
+
</template>
|
|
397
|
+
@endboostsnippet
|
|
398
|
+
@endverbatim
|
|
399
|
+
|
|
400
|
+
## Server-Side Patterns
|
|
401
|
+
|
|
402
|
+
Server-side patterns (Inertia::render, props, middleware) are covered in inertia-laravel guidelines.
|
|
403
|
+
|
|
404
|
+
## Common Pitfalls
|
|
405
|
+
|
|
406
|
+
- Using traditional `<a>` links instead of Inertia's `<Link>` component (breaks SPA behavior)
|
|
407
|
+
- Forgetting that Vue components must have a single root element
|
|
408
|
+
- Forgetting to add loading states (skeleton screens) when using deferred props
|
|
409
|
+
- Not handling the `undefined` state of deferred props before data loads
|
|
410
|
+
- Using `<form>` without preventing default submission (use `<Form>` component or `@submit.prevent`)
|
|
411
|
+
- Forgetting to check if `<Form>` component is available in your Inertia version
|