Skip to content

Commit 251df1f

Browse files
committed
fix(vuetify-nuxt-module): add configurable validation rules with custom file support
1 parent 171a695 commit 251df1f

File tree

7 files changed

+55
-11
lines changed

7 files changed

+55
-11
lines changed

apps/playground/app/pages/index.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
const { isRtl } = useRtl()
1212
const { width, height, name: displayName } = useDisplay()
1313
const theme = useTheme()
14+
const rules = useRules()
1415
1516
const isDark = computed({
1617
get: () => theme.global.name.value === 'dark',
@@ -24,6 +25,7 @@
2425
email: '',
2526
select: null,
2627
date: undefined,
28+
ruleValue: '',
2729
})
2830
2931
watch(isRtl, val => {
@@ -184,6 +186,21 @@
184186
</v-card>
185187
</v-col>
186188

189+
<!-- Validation Rules -->
190+
<v-col cols="12" md="6">
191+
<v-card height="100%" prepend-icon="i-mdi:check-circle-outline" title="Validation Rules">
192+
<v-card-text>
193+
<div class="text-subtitle-2 mb-2">Input Validation (useRules)</div>
194+
<v-text-field
195+
v-model="formData.ruleValue"
196+
label="Type something (min 3 chars)"
197+
:rules="[rules.required('Field is required'), rules.minLength(3, 'At least 3 characters')]"
198+
variant="outlined"
199+
/>
200+
</v-card-text>
201+
</v-card>
202+
</v-col>
203+
187204
<!-- SSR Info -->
188205
<v-col cols="12">
189206
<v-expansion-panels>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
required: (v: any) => !!v || 'Field is required (custom)',
3+
}

apps/playground/nuxt.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export default defineNuxtConfig({
4747
viewportSize: true,
4848
},
4949
styles: { configFile: '~/assets/custom-vuetify.scss', experimental: { cache: true } },
50+
rulesConfiguration: {
51+
fromLabs: true,
52+
configFile: '~/vuetify.rules.ts',
53+
},
5054
},
5155
},
5256
vite: {

packages/vuetify-nuxt-module/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ export interface MOptions {
313313
* @default true
314314
*/
315315
rulesConfiguration?: {
316-
fromLabs: boolean
316+
fromLabs?: boolean
317+
configFile?: string
317318
}
318319
/**
319320
* Vuetify SSR client hints.

packages/vuetify-nuxt-module/src/utils/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export interface VuetifyNuxtContext {
3232
vuetifyGte: (version: string) => boolean
3333
viteVersion: string
3434
enableRules?: boolean
35-
rulesConfiguration?: { fromLabs: boolean }
35+
rulesConfiguration?: { fromLabs?: boolean, configFile?: string }
3636
}
3737

3838
export async function loadVuetifyConfiguration<U extends ExternalVuetifyOptions> (

packages/vuetify-nuxt-module/src/utils/configure-nuxt.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export async function configureNuxt (
2323
const runtimeDir = ctx.resolver.resolve('./runtime')
2424

2525
// Automatically enable rules if not disabled
26-
if (ctx.enableRules !== undefined) {
26+
if (ctx.enableRules === undefined) {
2727
ctx.enableRules = ctx.vuetifyGte('3.8.0')
2828
}
2929

@@ -51,7 +51,20 @@ export async function configureNuxt (
5151
// transpile always vuetify and runtime folder
5252
nuxt.options.build.transpile.push(configKey, runtimeDir)
5353
if (ctx.enableRules) {
54-
nuxt.options.build.transpile.push(`#build/vuetify/${ctx.rulesConfiguration!.fromLabs ? 'labs-' : ''}rules-configuration.mjs`)
54+
const rulesConfigurationFile = `vuetify/${ctx.rulesConfiguration!.fromLabs ? 'labs-' : ''}rules-configuration.mjs`
55+
nuxt.options.build.transpile.push(`#build/${rulesConfigurationFile}`)
56+
addTemplate({
57+
filename: rulesConfigurationFile,
58+
getContents: async () => {
59+
if (ctx.rulesConfiguration?.configFile) {
60+
const resolvedPath = await resolvePath(ctx.rulesConfiguration.configFile)
61+
return `export { default as rulesOptions } from '${resolvedPath}'`
62+
}
63+
64+
return 'export const rulesOptions = {}'
65+
},
66+
write: true,
67+
})
5568
}
5669
// transpile vuetify nuxt plugin
5770
nuxt.options.build.transpile.push(/\/vuetify-nuxt-plugin\.(client|server)\.mjs$/)
@@ -98,12 +111,18 @@ export async function configureNuxt (
98111
composables.push('useMask')
99112
}
100113

101-
addImports(composables.map(name => ({
102-
name,
103-
from: ctx.vuetifyGte('3.4.0') || name !== 'useDate' ? 'vuetify' : 'vuetify/labs/date',
104-
as: prefixComposables ? name.replace(/^use/, 'useV') : undefined,
105-
meta: { docsUrl: name === 'useRules' ? 'https://vuetifyjs.com/en/features/rules/' : `https://vuetifyjs.com/en/api/${toKebabCase(name)}/` },
106-
})))
114+
addImports(composables.map(name => {
115+
let from = ctx.vuetifyGte('3.4.0') || name !== 'useDate' ? 'vuetify' : 'vuetify/labs/date'
116+
if (name === 'useRules' && ctx.rulesConfiguration?.fromLabs) {
117+
from = 'vuetify/labs/rules'
118+
}
119+
return {
120+
name,
121+
from,
122+
as: prefixComposables ? name.replace(/^use/, 'useV') : undefined,
123+
meta: { docsUrl: name === 'useRules' ? 'https://vuetifyjs.com/en/features/rules/' : `https://vuetifyjs.com/en/api/${toKebabCase(name)}/` },
124+
}
125+
}))
107126
}
108127

109128
if (ctx.ssrClientHints.enabled) {

packages/vuetify-nuxt-module/src/utils/vuetify-nuxt-plugins.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function addVuetifyNuxtPlugin (
4747

4848
let rulesImports = ''
4949
let rulesPlugin = ''
50-
if (mode === 'client' && ctx.enableRules) {
50+
if (ctx.enableRules) {
5151
rulesImports = [
5252
'',
5353
`import { rulesOptions } from '#build/vuetify/${ctx.rulesConfiguration!.fromLabs ? 'labs-' : ''}rules-configuration.mjs'`,

0 commit comments

Comments
 (0)