ui
ui copied to clipboard
Select Form - A form field element should have an id or name attribute
Receiving a browser issue in Chrome on the Select component
It looks like Form with Select has no id or name in SelectContent which is outside of the FormControl
<FormItem>
<div className="relative container mx-auto">
<FormLabel>
Title<sup className="text-red-600">*</sup>
</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value} value={field.value}>
<FormControl enableErrorHighlight>
<SelectTrigger className="sm:bg-white sm:focus:bg-slate-50 focus:placeholder:text-slate-500">
<SelectValue placeholder="Select" />
</SelectTrigger>
</FormControl>
<SelectContent className="bg-white max-h-80"> ==============={Missing 'id'}
<SelectItem value="[email protected]">[email protected]</SelectItem>
<SelectItem value="[email protected]">[email protected]</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</div>
</FormItem>
Label has correct 'for'
<label class="text-xs sm:text-sm font-normal text-slate-400 leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for=":r2:-form-item">Title<sup class="text-red-600">*</sup></label>
Button has correct 'id'
<button type="button" role="combobox" aria-controls="radix-:r3:" aria-expanded="false" aria-autocomplete="none" dir="ltr" data-state="closed" data-placeholder="" class="flex h-10 w-full items-center justify-between rounded-md border border-slate-100 bg-white px-3 py-2 text-slate-600 text-base font-normal ring-offset-background placeholder:text-slate-400 placeholder:font-extralight focus:bg-white focus:outline-none focus:ring-2 focus:ring-eivalue-blue-400 focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 sm:bg-white sm:focus:bg-slate-50 focus:placeholder:text-slate-500" id=":r2:-form-item" aria-describedby=":r2:-form-item-description" aria-invalid="false"><span style="pointer-events: none;">Select</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down h-4 w-4 opacity-50" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></button>
Select is missing 'id'. It is expecting an 'id' of id=":r2:-form-item"
<select aria-hidden="true" tabindex="-1" style="position: absolute; border: 0px; width: 1px; height: 1px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; overflow-wrap: normal;"><option value=""></option><option value="[email protected]">[email protected]</option><option value="[email protected]">[email protected]</option></select>
What have I tried: Adding id=":r2:-form-item" to SelectContent or SelectItem doesnt fix the issue either.
@Jamison1
You can remove the div
element and shift the className
attribute from div
to FormItem
element
<FormItem className="relative container mx-auto">
<FormLabel>
Title<sup className="text-red-600">*</sup>
</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value} value={field.value}>
<FormControl enableErrorHighlight>
<SelectTrigger className="sm:bg-white sm:focus:bg-slate-50 focus:placeholder:text-slate-500">
<SelectValue placeholder="Select" />
</SelectTrigger>
</FormControl>
<SelectContent className="bg-white max-h-80"> ==============={Missing 'id'}
<SelectItem value="[email protected]">[email protected]</SelectItem>
<SelectItem value="[email protected]">[email protected]</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</div>
</FormItem>
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.
I'm also running into this and not seeing a fix for it in the previous comments. It should be able to add an id to the select element so that it matches the label's htmlFor attribute and name. Been trying to figure this one out but no luck so far. @shadcn
This error shows up in the console issue warnings
@WillsWebsites
Can you provide the code for this??
@imopbuilder
Sure, this is my entire item in my form:
<FormField
control={form.control}
name="serviceType"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="serviceType">Type of Service</FormLabel>
<FormControl>
<Select
onValueChange={field.onChange}
defaultValue={field.value}
name={field.name}
disabled={isSubmitting}
>
<SelectTrigger>
<SelectValue placeholder="Select a service type" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Service types</SelectLabel>
<SelectItem value={ServiceType.DIAMOND}>
{FormattedServiceType[ServiceType.DIAMOND]}
</SelectItem>
<SelectItem value={ServiceType.GOLD}>
{FormattedServiceType[ServiceType.GOLD]}
</SelectItem>
<SelectItem value={ServiceType.SILVER}>
{FormattedServiceType[ServiceType.SILVER]}
</SelectItem>
<SelectItem value={ServiceType.GENERAL}>
{FormattedServiceType[ServiceType.GENERAL]}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</FormControl>
<FormDescription>
<Link href="/#packages" className="link text-gray-400">
Learn more
</Link>
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
It should allow an id prop on the element because the native select can receive it and when it has the id it solves the issue. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select
Looking into the radix component types it doesn't look like it even allows an id for some reason unless I'm missing something. Even on the shadcn website element page it has this same console warning because they don't have an id. I mean, this isn't even a field that could be autofilled in my case but I always like to make the label htmlFor attributes match the form element's id to avoid these console warnings and for best practice.
@WillsWebsites
I think currently you can pass the name
attribute as a workaround to solve the issue.
This is also discussed in Radix UI: https://github.com/radix-ui/primitives/discussions/2439#discussioncomment-8606491
Is there any fix for this? I hate having a form issue whenever I open the console. @shadcn
@Fingertips18 and @WillsWebsites
Here is the solution
'use client';
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@/components/ui/select';
import { zodResolver } from '@hookform/resolvers/zod';
import Link from 'next/link';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const ServiceType = {
DIAMOND: 'DIAMOND',
GOLD: 'GOLD',
SILVER: 'SILVER',
GENERAL: 'GENERAL',
};
const formSchema = z.object({
serviceType: z.string().min(2, {
message: 'Username must be at least 2 characters.',
}),
});
export function SelectForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
serviceType: '',
},
});
return (
<Form {...form}>
<FormField
control={form.control}
name='serviceType'
render={({ field }) => (
<FormItem>
<FormLabel htmlFor='serviceType'>Type of Service</FormLabel>
<FormControl>
<Select onValueChange={field.onChange} defaultValue={field.value} name={field.name}>
<SelectTrigger id='serviceType'>
<SelectValue placeholder='Select a service type' />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Service types</SelectLabel>
<SelectItem value={ServiceType.DIAMOND}>{ServiceType.DIAMOND}</SelectItem>
<SelectItem value={ServiceType.GOLD}>{ServiceType.GOLD}</SelectItem>
<SelectItem value={ServiceType.SILVER}>{ServiceType.SILVER}</SelectItem>
<SelectItem value={ServiceType.GENERAL}>{ServiceType.GENERAL}</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</FormControl>
<FormDescription>
<Link href='/#packages' className='link text-gray-400'>
Learn more
</Link>
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</Form>
);
}
Let me debug why there is a warning in the console.
Each label
element will have a htmlFor
attribute which should match the id
to any one of the dom-element
. When there is no match then you will get this warning.
when using FormControl
the FormControl
component automatically passes an id
to the child element, since the child element is a Select
component and will not take any id
attribute, there is no dom-element
matching id
attribute that matches the htmlFor
attribute of the label.
You can fix it by passing a htmlFor
value manually for both FormLabel
and SelectTrigger
as shown above
Notice that we are not passing the id
attribute to the Select
component because it will and be present in the html-dom
and only SelectTrigger
will be present in the dom