N
Nuxt3mo ago
WiFi Plug

nuxt ui form apply error on specific field

so i have a nuxt ui form with a signupschema but my api checks for compromised passwords so i want to display a zod like error on the password field if my api returns this. what's the cleanest way to do this
53 Replies
kapa.ai
kapa.ai3mo ago
Hi @WiFi Plug. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To display an error on a specific field (e.g., the password field) in a Nuxt UI form when your API returns a custom error (like "compromised password"), you should use the exposed form instance methods, specifically setErrors. This allows you to programmatically set errors on individual fields after your API response, mimicking Zod-style errors. Here's the cleanest approach: 1. Expose the form instance using useTemplateRef. 2. On API response, if the password is compromised, call form.value.setErrors with the appropriate error object for the password field. Example
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent, FormError } from '@nuxt/ui'

const form = useTemplateRef('form')

const schema = z.object({
email: z.string().email('Invalid email'),
password: z.string().min(8, 'Must be at least 8 characters')
})

const state = reactive({
email: '',
password: ''
})

async function onSubmit(event: FormSubmitEvent<typeof state>) {
// Simulate API call
const apiResponse = await fakeApiCheck(state.password)
if (apiResponse.compromised) {
// Set error on password field
form.value?.setErrors([
{ name: 'password', message: 'This password has been compromised. Please choose another.' }
])
return
}
// Continue with normal flow
// ...
}

// Fake API function for demonstration
async function fakeApiCheck(password: string) {
return { compromised: password === '123456' }
}
</script>

<template>
<UForm ref="form" :schema="schema" :state="state" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">Submit</UButton>
</UForm>
</template>
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent, FormError } from '@nuxt/ui'

const form = useTemplateRef('form')

const schema = z.object({
email: z.string().email('Invalid email'),
password: z.string().min(8, 'Must be at least 8 characters')
})

const state = reactive({
email: '',
password: ''
})

async function onSubmit(event: FormSubmitEvent<typeof state>) {
// Simulate API call
const apiResponse = await fakeApiCheck(state.password)
if (apiResponse.compromised) {
// Set error on password field
form.value?.setErrors([
{ name: 'password', message: 'This password has been compromised. Please choose another.' }
])
return
}
// Continue with normal flow
// ...
}

// Fake API function for demonstration
async function fakeApiCheck(password: string) {
return { compromised: password === '123456' }
}
</script>

<template>
<UForm ref="form" :schema="schema" :state="state" @submit="onSubmit">
<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>
<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>
<UButton type="submit">Submit</UButton>
</UForm>
</template>
- The key is using form.value?.setErrors([{ name: 'password', message: '...' }]) to set the error on the password field after your API check. - This approach works seamlessly with Zod or any schema validation, and integrates with Nuxt UI's error display system for fields. References:
- Form Expose API
- Custom Validation and Error Handling ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai should i bing :loading to my nuxt ui form loading being set to true while im doing my api call?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You generally do not need to manually bind the :loading prop to your Nuxt UI form while performing an API call if you are using the default behavior. The Nuxt UI <UForm> component has a loadingAuto prop (enabled by default), which will automatically set all form elements to a loading/disabled state during the @submit event. This means inputs will be disabled and loading indicators will show as appropriate while your async submit handler is running. If you want to control the loading state manually (for example, if you have a more complex flow or want to show loading outside of the default submit lifecycle), you can use the :loading prop and set it to true while your API call is in progress. But for most use cases, the default loadingAuto behavior is sufficient and recommended for simplicity Nuxt UI Form Props Nuxt UI Button Loading. Summary:
- By default, you do not need to manually bind :loadingloadingAuto handles it. - Use :loading only if you need custom/manual control over the loading state. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai
<template>
<UForm
ref="form"
:schema="SignUpSchema"
:state="state"
class="space-y-4"
@submit="onSubmit"
>
<UFormField label="Name" name="name">
<UInput v-model="state.name" />
</UFormField>

<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>

<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>

<UFormField label="Confirm Password" name="confirmPassword">
<UInput v-model="state.confirmPassword" type="password" />
</UFormField>

<UFormField name="terms">
<UCheckbox v-model="state.terms" label="I agree to the terms and conditions" />
</UFormField>

<NuxtTurnstile ref="turnstile" v-model="turnstileToken" />

<UAlert
v-if="error"
color="error"
variant="subtle"
title="Error Signing Up"
:description="error.message"
icon="i-lucide-triangle-alert"
/>

<UButton
type="submit"
:disabled="!turnstileToken"
label="Sign Up"
/>
</UForm>
</template>
<template>
<UForm
ref="form"
:schema="SignUpSchema"
:state="state"
class="space-y-4"
@submit="onSubmit"
>
<UFormField label="Name" name="name">
<UInput v-model="state.name" />
</UFormField>

<UFormField label="Email" name="email">
<UInput v-model="state.email" />
</UFormField>

<UFormField label="Password" name="password">
<UInput v-model="state.password" type="password" />
</UFormField>

<UFormField label="Confirm Password" name="confirmPassword">
<UInput v-model="state.confirmPassword" type="password" />
</UFormField>

<UFormField name="terms">
<UCheckbox v-model="state.terms" label="I agree to the terms and conditions" />
</UFormField>

<NuxtTurnstile ref="turnstile" v-model="turnstileToken" />

<UAlert
v-if="error"
color="error"
variant="subtle"
title="Error Signing Up"
:description="error.message"
icon="i-lucide-triangle-alert"
/>

<UButton
type="submit"
:disabled="!turnstileToken"
label="Sign Up"
/>
</UForm>
</template>
so this is properly implemented as clean as can be?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Your implementation is very close to best practices for a Nuxt UI form, but there are a few points to consider for maximum cleanliness and alignment with Nuxt UI conventions: 1. Form Loading State:
You are not using the loading or loading-auto prop on your <UButton>. By default, Nuxt UI forms handle loading automatically (loadingAuto is true), but to provide a better user experience, you should add the loading-auto prop to your submit button. This will show a loading indicator and disable the button while the form is submitting, without needing to manage loading state manually (Button Loading).
<UButton
type="submit"
:disabled="!turnstileToken"
label="Sign Up"
loading-auto
/>

<UButton
type="submit"
:disabled="!turnstileToken"
label="Sign Up"
loading-auto
/>

2. Error Handling:
Displaying a general error with <UAlert> is good. If you want to show field-specific errors (e.g., from your API), use the form's setErrors method as discussed previously (Form Expose). 3. Validation:
Using :schema and :state is correct and recommended (Form Schema Validation). 4. Accessibility:
Your use of label and name on UFormField is correct and ensures accessibility. 5. External Controls:
Disabling the submit button when !turnstileToken is a good practice for external validation. Summary:
- Add loading-auto to your submit button for a better UX. - Otherwise, your implementation follows Nuxt UI best practices for a clean and maintainable form. If you want to handle field-specific errors from your API, remember to use the form's setErrors method as shown in the previous answer. References:
- Nuxt UI Form Schema Validation
- Nuxt UI Button Loading
- Nuxt UI Form Expose ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai and the :disabled thing would work correctly to ensure it's disabled if no turnstile token but still disable it based on the form?
<script setup lang="ts">
import { SignUpSchema } from "~/lib/db/schema";

const state = reactive<Partial<SignUpUser>>({
name: undefined,
email: undefined,
password: undefined,
confirmPassword: undefined,
terms: false,
});

const form = useTemplateRef("form");

const turnstile = ref();
const turnstileToken = ref("");

const loading = ref(false);
const error = ref<APIError | null>(null);

const { signUpEmail } = useAuthStore();

async function onSubmit(event: FormSubmitEvent<SignUpUser>) {
if (!turnstileToken.value)
return;

loading.value = true;
error.value = null;

try {
await new Promise(resolve => setTimeout(resolve, 10000));
await signUpEmail(event.data, turnstileToken.value);
await navigateTo("/dashboard");
}
catch (e) {
error.value = e as APIError;

if (error.value.code === "PASSWORD_COMPROMISED") {
form.value?.setErrors([
{ name: "password", message: error.value.message },
]);
}

turnstile.value?.reset();
turnstileToken.value = "";
}
finally {
loading.value = false;
}
}
</script>
<script setup lang="ts">
import { SignUpSchema } from "~/lib/db/schema";

const state = reactive<Partial<SignUpUser>>({
name: undefined,
email: undefined,
password: undefined,
confirmPassword: undefined,
terms: false,
});

const form = useTemplateRef("form");

const turnstile = ref();
const turnstileToken = ref("");

const loading = ref(false);
const error = ref<APIError | null>(null);

const { signUpEmail } = useAuthStore();

async function onSubmit(event: FormSubmitEvent<SignUpUser>) {
if (!turnstileToken.value)
return;

loading.value = true;
error.value = null;

try {
await new Promise(resolve => setTimeout(resolve, 10000));
await signUpEmail(event.data, turnstileToken.value);
await navigateTo("/dashboard");
}
catch (e) {
error.value = e as APIError;

if (error.value.code === "PASSWORD_COMPROMISED") {
form.value?.setErrors([
{ name: "password", message: error.value.message },
]);
}

turnstile.value?.reset();
turnstileToken.value = "";
}
finally {
loading.value = false;
}
}
</script>
this is the script part of my code is this optimal?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, your approach to disabling the submit button with :disabled="!turnstileToken" will ensure the button is disabled when there is no Turnstile token. However, this only covers the Turnstile check. If you want the button to also be disabled during form submission (i.e., while loading is true), you should combine both conditions:
<UButton
type="submit"
:disabled="!turnstileToken || loading"
label="Sign Up"
loading-auto
/>
<UButton
type="submit"
:disabled="!turnstileToken || loading"
label="Sign Up"
loading-auto
/>
But, if you use the loading-auto prop on <UButton>, Nuxt UI will automatically disable the button during form submission, so you only need to check for the Turnstile token:
<UButton
type="submit"
:disabled="!turnstileToken"
label="Sign Up"
loading-auto
/>
<UButton
type="submit"
:disabled="!turnstileToken"
label="Sign Up"
loading-auto
/>
This way, the button is: - Disabled if there is no Turnstile token (!turnstileToken) - Automatically disabled and shows a loading indicator while the form is submitting, thanks to loading-auto (Button Loading). Summary:
- Your use of :disabled="!turnstileToken" is correct for the Turnstile check. - Add loading-auto to <UButton> for automatic disabling/loading during submission. - You do not need to manually manage the loading state for the button if you use loading-auto. This approach is optimal and aligns with Nuxt UI best practices for form and button state management Form Props Button Loading. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai ah so i could have removed my loading ref entirely, i just did that and it still works nicely with loading-auto on the form
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, that's correct! With loading-auto on the <UButton>, Nuxt UI automatically manages the loading and disabled state of the button during form submission. You do not need to manually manage a loading ref for this purpose—the form and button will handle it for you. This is the recommended and cleanest approach according to the Nuxt UI documentation Button Loading. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai and i removed this " turnstileToken.value = "";" instead relying on turnstile.value?.reset() is that fine since that should empty the ref
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I'm sorry, but the knowledge sources do not contain explicit information about the behavior of turnstile.value?.reset() and whether it will automatically clear the turnstileToken ref in your specific implementation. If turnstile.value?.reset() is designed to reset the token and update the bound v-model, then removing turnstileToken.value = "" should be fine. However, without documentation or source code confirming this behavior, I cannot state this with certainty. Please verify this behavior in your component or refer to the documentation for NuxtTurnstile if available. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai what's the difference between ref and useTemplateRef when storing a reference to my form so i can set errors manually
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The main difference between ref and useTemplateRef when storing a reference to your form in Nuxt 3 (and Vue 3.5+) is that useTemplateRef is the recommended way to reference a template ref for HTML elements or components, especially in <script setup>. This is now the standard approach in Nuxt UI and other Nuxt/Vue documentation. - ref is a general-purpose reactivity primitive for storing any reactive value. - useTemplateRef is specifically designed for template refs, making it easier and more type-safe to access component or element instances referenced in your template. For example, to access your form instance and call methods like setErrors, you should use:
const form = useTemplateRef('form')
const form = useTemplateRef('form')
And in your template:
<UForm ref="form" ... />
<UForm ref="form" ... />
This approach is shown throughout the Nuxt UI documentation for accessing component APIs, such as forms, tables, carousels, etc. (Nuxt UI Form Expose). In summary:
- Use useTemplateRef for template refs in Nuxt 3/Vue 3.5+ for better integration and type safety. - ref is more generic and not tailored for template refs in this context. References:
- Nuxt UI Form Expose
- Nuxt UI Table Expose
- Nuxt UI Carousel Expose
- Nuxt UI AuthForm Expose
- Nuxt UI Stepper Expose
- Nuxt docs update to useTemplateRef ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai should my turnstile ref be a template ref too then?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources do not contain explicit information about whether your Turnstile ref (for <NuxtTurnstile ref="turnstile" />) should be a template ref using useTemplateRef or a standard ref. However, the general pattern in Nuxt UI and related documentation is to use useTemplateRef for referencing component instances in the template, as it provides better integration and type safety, especially when you want to access exposed methods or properties on the component instance Nuxt UI Form Expose Nuxt UI Stepper Expose. If your Turnstile component exposes methods (like reset) that you want to call from your script, using useTemplateRef('turnstile') is recommended for consistency with Nuxt UI best practices. If you only need a simple reactive value and do not need to access component methods, a standard ref may suffice. In summary:
- Use useTemplateRef for template refs to component instances when you need to access their methods or properties. - The knowledge sources do not provide a specific example for Turnstile, but this is the recommended pattern for other components in Nuxt UI. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai so when using " form.value?.setErrors([ { name: "password", message: error.value.message }, ]);" to set a custom zod error on a specific field it works but if i click that field and click off it gets revalidated and removed. is that optimal UX or should it remain until the user resubmits the form?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources explain that when you use setErrors to set a custom error on a specific field (such as the password field), the error is displayed on that field. However, the Nuxt UI Form component is designed to automatically revalidate fields on certain events (like blur, input, or change), and this can clear the error if the field passes validation after the user interacts with it (Input Events). This behavior is intentional and aligns with standard UX patterns:
- Field errors are cleared when the user corrects the input or interacts with the field, so users are not blocked by stale errors. - If you want the error to persist until the next form submission, you would need to customize the validation logic or error handling, but this is not the default or recommended behavior in Nuxt UI. In summary:
The default behavior—where the error is cleared on revalidation after user interaction—is considered optimal UX and is how Nuxt UI is designed to work (Custom Validation). This gives immediate feedback and avoids confusing the user with errors that may no longer be relevant. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai right but this error that i manually apply comes from my server side validation for example validating a referral code when the user submits the form. but client side the referral field is optional in the zod validation schema. so what happens is the user clicks the referral code field > clicks off > invalid referral code error is gone which doesn't seem ideal as they should resubmit the form again (or clear the error if they make the field empty)
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources confirm that Nuxt UI's form validation system will clear errors on a field when it is revalidated—such as on blur, input, or change events—if the field passes the client-side schema validation (Input Events). Since your referral code field is optional in the Zod schema, any server-side error you set with setErrors will be removed as soon as the user interacts with the field and it passes the (non-restrictive) client-side validation. The documentation does not provide a built-in way to persist server-side errors on a field until the next submission, nor does it discuss best practices for this specific scenario. Therefore, based on the knowledge sources, this is the default and expected behavior in Nuxt UI:
- Field errors are cleared on revalidation, even if they were set manually from the server. If you want to change this behavior (e.g., to keep the server error until the user resubmits or clears the field), you would need to implement custom logic, but the knowledge sources do not provide guidance or examples for this pattern. Summary:
- The current behavior (error cleared on blur if field passes client-side validation) is by design in Nuxt UI. - The knowledge sources do not describe a built-in way to persist server-side errors until resubmission or field change. References:
- Nuxt UI Form Input Events - Nuxt UI Form Custom Validation ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai for my password field I made a custom component to display the requirements the user should fill in (it's shown whenever there's anything typed in the password input and while not all requirements are met). is there a clean way to ensure that i only get the zod error color on the input field but not the text underneath as ill use my component instead
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources do not explicitly describe a built-in way in Nuxt UI to apply the error color only to the input field while suppressing the default error/help text below, especially when using a custom password requirements component. However, you can achieve this by controlling the error prop on the <UFormField> and using slots. - The error prop on <UFormField> controls both the error color on the input and the error message below (FormField Error). - If you set error to true (instead of a string), the error color will be applied to the input, but no error message will be shown below. This allows you to display your own custom requirements component underneath the input without the default error text interfering. Example:
<UFormField
label="Password"
name="password"
:error="hasZodError ? true : false"
>
<UInput v-model="state.password" type="password" />
<template #default>
<PasswordRequirements v-if="showRequirements" :value="state.password" />
</template>
</UFormField>
<UFormField
label="Password"
name="password"
:error="hasZodError ? true : false"
>
<UInput v-model="state.password" type="password" />
<template #default>
<PasswordRequirements v-if="showRequirements" :value="state.password" />
</template>
</UFormField>
- hasZodError should be true if there is a Zod validation error for the password field. - By passing true (not a string) to error, you get the error color on the input but suppress the default error message, letting your custom component handle the requirements display. This approach is clean and leverages Nuxt UI's documented API for error handling and slot customization (FormField API). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai thanks, and how should i properly deduce whether or not the field has a zod error?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To properly deduce whether a field (such as your password field) has a Zod error in a Nuxt UI form, you should use the form instance’s exposed API. When you reference your form with useTemplateRef('form'), you gain access to the getErrors(path) method, which returns an array of errors for a specific field name (Form Expose). Example:
const form = useTemplateRef('form')

// In your computed or method:
const hasPasswordError = computed(() => {
return (form.value?.getErrors('password')?.length ?? 0) > 0
})
const form = useTemplateRef('form')

// In your computed or method:
const hasPasswordError = computed(() => {
return (form.value?.getErrors('password')?.length ?? 0) > 0
})
You can then use hasPasswordError to control the error prop on your <UFormField>:
<UFormField
label="Password"
name="password"
:error="hasPasswordError ? true : false"
>
<!-- ... -->
</UFormField>
<UFormField
label="Password"
name="password"
:error="hasPasswordError ? true : false"
>
<!-- ... -->
</UFormField>
This approach ensures you are checking for any validation errors (including Zod errors) on the password field in a way that is fully supported and recommended by Nuxt UI’s API.
For more details, see the Form Expose documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai "'hasPasswordError' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.ts-plugin(7022) const hasPasswordError: any" how should i type it properly? "'form' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.ts-plugin(7022) const form: any"
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources do not provide explicit TypeScript types for the result of useTemplateRef or for the computed property that checks for field errors. However, the Nuxt UI documentation shows usage of useTemplateRef for accessing the form instance and its methods, such as getErrors, but does not specify the exact types to use for TypeScript (Form Expose). Given this, you can type your form ref as any or use a more specific type if you know the structure, but the documentation does not provide a ready-made type. For the computed property, you can explicitly annotate it as ComputedRef<boolean> to satisfy TypeScript. Example:
import { computed, ComputedRef } from 'vue'

const form = useTemplateRef('form') as any // No explicit type in docs

const hasPasswordError: ComputedRef<boolean> = computed(() => {
return (form.value?.getErrors('password')?.length ?? 0) > 0
})
import { computed, ComputedRef } from 'vue'

const form = useTemplateRef('form') as any // No explicit type in docs

const hasPasswordError: ComputedRef<boolean> = computed(() => {
return (form.value?.getErrors('password')?.length ?? 0) > 0
})
- form is typed as any because the knowledge sources do not provide a more specific type. - hasPasswordError is typed as ComputedRef<boolean>. If Nuxt UI provides types in the future, you can update these accordingly, but based on the current documentation, this is the most accurate approach available from the knowledge sources. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai so " <UFormField label="Password" name="password" required :error="hasPasswordError" > <UInput v-model="state.password" :type="showPassword ? 'text' : 'password'" icon="i-heroicons-lock-closed" placeholder="Choose a strong password" autocomplete="new-password" :ui="{ trailing: 'pe-1' }" @input="clearServerError('password')" > <template #trailing> <UButton color="neutral" variant="ghost" :icon="showPassword ? 'i-heroicons-eye-slash-20-solid' : 'i-heroicons-eye-20-solid'" @click="showPassword = !showPassword" /> </template> </UInput> <!-- Show my custom password requirements here conditionally and strength indicator --> </UFormField>' in my form should i put my custom password requirements component inside the formfield or not
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, you should place your custom password requirements component inside the <UFormField> as a child, typically below the <UInput>. This is consistent with how Nuxt UI demonstrates placing additional information, such as help text, hints, or custom content, within a form field (FormField Usage). By placing your custom component inside <UFormField>, you ensure it is visually grouped with the password input and benefits from the same layout and accessibility structure. You can conditionally render your requirements component based on your logic (e.g., when the user has started typing or not all requirements are met). Example:
<UFormField
label="Password"
name="password"
required
:error="hasPasswordError"
>
<UInput
v-model="state.password"
:type="showPassword ? 'text' : 'password'"
icon="i-heroicons-lock-closed"
placeholder="Choose a strong password"
autocomplete="new-password"
:ui="{ trailing: 'pe-1' }"
@input="clearServerError('password')"
>
<template #trailing>
<UButton
color="neutral"
variant="ghost"
:icon="showPassword ? 'i-heroicons-eye-slash-20-solid' : 'i-heroicons-eye-20-solid'"
@click="showPassword = !showPassword"
/>
</template>
</UInput>

<!-- Place your custom requirements component here -->
<PasswordRequirements
v-if="state.password && !allRequirementsMet"
:value="state.password"
/>
</UFormField>
<UFormField
label="Password"
name="password"
required
:error="hasPasswordError"
>
<UInput
v-model="state.password"
:type="showPassword ? 'text' : 'password'"
icon="i-heroicons-lock-closed"
placeholder="Choose a strong password"
autocomplete="new-password"
:ui="{ trailing: 'pe-1' }"
@input="clearServerError('password')"
>
<template #trailing>
<UButton
color="neutral"
variant="ghost"
:icon="showPassword ? 'i-heroicons-eye-slash-20-solid' : 'i-heroicons-eye-20-solid'"
@click="showPassword = !showPassword"
/>
</template>
</UInput>

<!-- Place your custom requirements component here -->
<PasswordRequirements
v-if="state.password && !allRequirementsMet"
:value="state.password"
/>
</UFormField>
This approach is in line with Nuxt UI's examples, where additional content (like help or custom components) is placed inside the form field for clarity and accessibility (FormField Help). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai " <UFormField label="Password" name="password" required :error="hasPasswordError" > <UInput v-model="state.password" :type="showPassword ? 'text' : 'password'" icon="i-heroicons-lock-closed" placeholder="Choose a strong password" autocomplete="new-password" :ui="{ trailing: 'pe-1' }" @input="clearServerError('password')" > <template #trailing> <UButton color="neutral" variant="ghost" :icon="showPassword ? 'i-heroicons-eye-slash-20-solid' : 'i-heroicons-eye-20-solid'" @click="showPassword = !showPassword" /> </template> </UInput> <PasswordStrength :password="state.password" /> </UFormField>" how should i go about adding a gap between the input and my strength component
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources do not mention a built-in prop on <UFormField> or <UInput> specifically for adding spacing between the input and custom content like your <PasswordStrength> component. However, Nuxt UI examples show that you can use standard utility classes (such as Tailwind CSS classes) to add spacing between elements inside a form field. A clean approach is to wrap your custom component in a <div> and apply a margin utility class, such as mt-2 or mt-4, to create a gap between the input and the strength indicator:
<UFormField
label="Password"
name="password"
required
:error="hasPasswordError"
>
<UInput
v-model="state.password"
:type="showPassword ? 'text' : 'password'"
icon="i-heroicons-lock-closed"
placeholder="Choose a strong password"
autocomplete="new-password"
:ui="{ trailing: 'pe-1' }"
@input="clearServerError('password')"
>
<template #trailing>
<UButton
color="neutral"
variant="ghost"
:icon="showPassword ? 'i-heroicons-eye-slash-20-solid' : 'i-heroicons-eye-20-solid'"
@click="showPassword = !showPassword"
/>
</template>
</UInput>

<div class="mt-2">
<PasswordStrength :password="state.password" />
</div>
</UFormField>
<UFormField
label="Password"
name="password"
required
:error="hasPasswordError"
>
<UInput
v-model="state.password"
:type="showPassword ? 'text' : 'password'"
icon="i-heroicons-lock-closed"
placeholder="Choose a strong password"
autocomplete="new-password"
:ui="{ trailing: 'pe-1' }"
@input="clearServerError('password')"
>
<template #trailing>
<UButton
color="neutral"
variant="ghost"
:icon="showPassword ? 'i-heroicons-eye-slash-20-solid' : 'i-heroicons-eye-20-solid'"
@click="showPassword = !showPassword"
/>
</template>
</UInput>

<div class="mt-2">
<PasswordStrength :password="state.password" />
</div>
</UFormField>
This method is consistent with Nuxt UI documentation, which uses utility classes for spacing in similar scenarios (FormField Help Example). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai "<PasswordStrength v-show="typeof passwordError !== 'string'" :password="state.password" />' is this a clean way to hide my password strength component if password error is a string? as that can be a boolean, string or undefined
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources do not explicitly discuss using v-show or conditional rendering for custom components like <PasswordStrength> based on the type of an error value. However, they do show that the error prop on <UFormField> can accept a string, boolean, or undefined (FormField API), and that you can control the display of custom content inside a form field using standard Vue conditional rendering. Using v-show="typeof passwordError !== 'string'" is a reasonable and clean way to hide your password strength component when passwordError is a string (i.e., when there is a validation error message), since this matches the possible types for the error prop. This approach is consistent with Vue best practices and does not conflict with any Nuxt UI recommendations in the knowledge sources. Summary:
Yes, using v-show="typeof passwordError !== 'string'" to conditionally display your <PasswordStrength> component is a clean and valid approach, given the types supported by the error prop in Nuxt UI FormField API. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai on my UIinputs inside formfields do i need to apply class="block" to them all? to make them full width
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You do not need to apply class="block" to all your <UInput> components inside <UFormField> to make them full width. Instead, you should use class="w-full" on the input to ensure it takes the full width of its container, as shown in the Nuxt UI documentation examples:
<UFormField label="Email" help="We won't share your email." required>
<UInput v-model="email" placeholder="Enter your email" icon="i-lucide-at-sign" class="w-full" />
</UFormField>
<UFormField label="Email" help="We won't share your email." required>
<UInput v-model="email" placeholder="Enter your email" icon="i-lucide-at-sign" class="w-full" />
</UFormField>
The documentation consistently uses w-full for full-width inputs, not block FormField Usage. If you want your inputs to span the full width, use w-full rather than block. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi PlugOP3mo ago
@kapa.ai what about globally applying it to uinputs
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The knowledge sources do not explicitly mention a built-in way to globally apply w-full (or any class) to all <UInput> components in Nuxt UI. However, you can globally override the default styles of Nuxt UI components using the app.config.ts file by customizing the component's theme slots Customize theme Config. For <UInput>, you would add the w-full class to the appropriate slot (usually base or root) in your app.config.ts:
export default defineAppConfig({
ui: {
input: {
slots: {
base: 'w-full'
}
}
}
})
export default defineAppConfig({
ui: {
input: {
slots: {
base: 'w-full'
}
}
}
})
This will apply w-full to all <UInput> components by default throughout your application, so you don't have to add it manually each time. For more details, see the Nuxt UI theme customization documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@679734274840330384> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?