Closed JungRama closed 2 weeks ago
I am having a similar issue too. It seems that "dynamically" generated SelectItem
is causing an issue. In my case, I am using Zod
validation library. I am supposed to select from available types of properties. The selection works and Zod is getting the value. But the item is not being displayed in the select box. It is just showing empty
<FormField
control={form.control}
name="type"
render={({ field }) => (
<FormItem className="grid grid-cols-4 items-center gap-4">
<FormLabel className="sm:block sm:text-right">
Type
</FormLabel>
<Select
disabled={isSubmitting}
onValueChange={field.onChange}
defaultValue={field.value}
>
<FormControl>
<SelectTrigger className="col-span-4 sm:col-span-3">
<SelectValue placeholder="Select a property type"/>
</SelectTrigger>
</FormControl>
<SelectContent className="SelectContent">
{propTypes.map((type) => (
<SelectItem key={type.id} value={type.id}>
{type.name}
</SelectItem>
))}
</SelectContent>
</Select>
</FormItem>
)}
/>
I am not seeing the value selected:
However, Zod is getting the value successfully:
Now, if I replace the dynamically generated values with static values as below, it will work, and I will be able to see what I selected:
<SelectContent>
<SelectItem value="m@example.com">m@example.com</SelectItem>
<SelectItem value="m@google.com">m@google.com</SelectItem>
<SelectItem value="m@support.com">m@support.com</SelectItem>
</SelectContent>
Something is wrong when we generate the SelectItem
dynamically
Here is codesandbox view for your reference
@yousihy , have you resolved this?
@yousihy @codingwithashu I hope you are aware of the fact that defaultValue
should be used only when you do not need to control the state of the select. You might need to use value
instead. See This
I was also having trouble getting this to work. But @hardikchopra242 nailed it for me. The example of usage in a form in the docs leads to this mistake (defaultValue instead of value).
@yousihy , have you resolved this?
For my case, the issue was that I needed to strictly specify that the value is a string
although the type was a string
. This applies to ALL shadcn
controls by the way.
So, I had to convert the string
to a string
value={data.id.toString()}
So, the SelectContent
would look like this:
<SelectContent>
{propType.map((data)=>(
<SelectItem key={data.id} value={data.id.toString()}>{data.name}</SelectItem>
))}
</SelectContent>
@yousihy @codingwithashu I hope you are aware of the fact that
defaultValue
should be used only when you do not need to control the state of the select. You might need to usevalue
instead. See This
This did not work for me or it didn't have any effect on my problem. My controls are working fine with value
only. My issue was that I needed to ensure that I am passing a string
to the value
property of the SelectItem
even though the type of that value is actually a string. See my comment above
@yousihy Thanks!
data.id.toString()
this saved me to waste much more time on this
Not worked
@codingwithashu
Not worked
First of all, if you are using value, there is no reason to also use defaultValue.
Inside
try if it works
Not worked
Can you upload or write your code in a codesandbox so we can look at it? Maybe we can help
I set defaultValue is formfield attribut and value at Selectitem, I set value equal defaultValue (I think defaultValue can use value.key but my defaultValue is same value.name ).
@yousihy @codingwithashu I hope you are aware of the fact that
defaultValue
should be used only when you do not need to control the state of the select. You might need to usevalue
instead. See This
It works 👍
For set the defaulValues for the form use:
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: "your values" ,
});
As the Radix docs state: If you need more flexibility, you can control the component using value/onValueChange props and passing children to SelectValue.
solved 💯 ;) 👍 🥇
Actually, due to the fact that shadcn uses radix in itself and when you are importing the select component, it is probably wrongly imported from radix and you just need to import it from the select component related to shadcn. This was the problem with my code and I realized it after a few days
import { SelectItem, SelectValue } from "@radix-ui/react-select"; //wrong import
import {SelectItem, SelectValue } from "@/components/ui/select"; //correct import
As the Radix docs state:
If you need more flexibility, you can control the component using value/onValueChange props and passing children to SelectValue.
This fixed my issue.
Where is the entire code that works?
I've found the best way is to set the defaultValue
to be the value from your source object, rather than the field.value
.
When the source object loads the select will re-render correctly to show the original object value.
This wasn't the case when using value={field.value ? field.value.toString() : undefined}
, it would always be undefined even after the object had loaded and other fields had re-rendered with the object values.
I wonder if it's because of the number -> string conversion?
<FormField
control={userForm.control}
name="roleId"
render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select onValueChange={field.onChange} defaultValue={user.roleId.toString()}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select a Role for this User" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="0">Reader</SelectItem>
<SelectItem value="1">Standard</SelectItem>
<SelectItem value="2">Admin</SelectItem>
<SelectItem value="3">Owner</SelectItem>
</SelectContent>
</Select>
<FormDescription>
Security level for this user. This will determine what they can do.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
Hi all,
What if I want the value
in a form
submission to be of type object
and not string
?
For example I want to select an item but that item is an object "behind the scenes" and not a simple string.
Is there a possibility to do that?
Thanks.
Pass what you want as a default as props const ListItems= (value: string) => {}
Select onValueChange={handleChange} defaultValue={value.toString()}
it worked for me. i hope it will work for you
Is there a solution ?
I did it like this and it worked...
Using nextjs 14 in a form with zod:
const form = useForm<z.infer<typeof UpdateCompanyFormSchema>>({
resolver: zodResolver(UpdateCompanyFormSchema),
defaultValues: {
companyId: companySelected?.id.toString() || "",
},
});
useEffect(() => {
if (companySelected) {
form.setValue("companyId", companySelected.id.toString());
}
}, [companySelected, form]);
<FormItem>
<FormLabel>Nome da empresa</FormLabel>
<Select
onValueChange={field.onChange}
defaultValue={field.value || ""}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Selecione a empresa" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectGroup>
<SelectLabel>ATIVAS</SelectLabel>
{companies
.filter((company) => company.active)
.map((company) => (
<SelectItem
key={company.id}
value={company.id.toString()}
>
{company.name}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>INATIVAS</SelectLabel>
{companies
.filter((company) => !company.active)
.map((company) => (
<SelectItem
key={company.id}
value={company.id.toString()}
className="text-gray-700"
>
{company.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<FormDescription>Nome da empresa</FormDescription>
<FormMessage />
</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 have a button with action to set a sorting on select input. On that button i change the value on useState from latest -> price-low-high.
When the button clicked the value inside render-value class changed. but the default value for the select not changed.
const [sort, setSort] = useState<string>('latest')