Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default value not showing the correct selected value #1361

Closed
JungRama opened this issue Aug 27, 2023 · 27 comments
Closed

Default value not showing the correct selected value #1361

JungRama opened this issue Aug 27, 2023 · 27 comments
Labels

Comments

@JungRama
Copy link

JungRama commented Aug 27, 2023

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')

<div className="flex items-center w-full md:w-auto">
  <div className="render-value">{sort}</div>
  <button onClick={()=> setSort('price-low-high')}>CHANGE SORT VALUE<button>

  <Label htmlFor="sorting" className="mr-2 text-gray-500 hidden md:block">Sorting {sort}</Label>
  <Select onValueChange={value=> selectSort(value)}
    defaultValue={sort}>
    <SelectTrigger className="w-full md:w-[200px]">
      <SelectValue placeholder="Select Sorting" />
    </SelectTrigger>
    <SelectContent id="sorting">
      <SelectItem value="latest">Latest Product {sort}</SelectItem>
      <SelectItem value={'price-low-high'}>Price: Low - High</SelectItem>
      <SelectItem value={'price-high-low'}>Price: High - Low</SelectItem>
    </SelectContent>
  </Select>
</div>
@yousihy
Copy link

yousihy commented Sep 6, 2023

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>
)}
/>

image

I am not seeing the value selected:

image

However, Zod is getting the value successfully:

image

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="[email protected]">[email protected]</SelectItem>
   <SelectItem value="[email protected]">[email protected]</SelectItem>
   <SelectItem value="[email protected]">[email protected]</SelectItem>
</SelectContent>

Something is wrong when we generate the SelectItem dynamically

@yousihy
Copy link

yousihy commented Sep 6, 2023

Here is codesandbox view for your reference

codesandbox view

@codingwithashu
Copy link

@yousihy , have you resolved this?

@hardikchopra242
Copy link

@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

@lucas-mirror
Copy link

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).

image

@yousihy
Copy link

yousihy commented Sep 22, 2023

@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
Copy link

yousihy commented Sep 22, 2023

@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

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

@Yolosopher2
Copy link

@yousihy Thanks!

data.id.toString()

this saved me to waste much more time on this

@codingwithashu
Copy link

Not worked
image

@Yolosopher2
Copy link

@codingwithashu

Not worked image

First of all, if you are using value, there is no reason to also use defaultValue.

Inside attributes comment "value" and "onValueChange". And add .toString() inside defaultValue like this: defaultValue={field.value.toString()} try if it works

@yousihy
Copy link

yousihy commented Sep 22, 2023

Not worked image

Can you upload or write your code in a codesandbox so we can look at it? Maybe we can help

@MrKeem
Copy link

MrKeem commented Sep 30, 2023

image
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 ).

@webdiego
Copy link

webdiego commented Oct 7, 2023

@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

It works 👍

For set the defaulValues for the form use:

const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
    defaultValues: "your values" ,
  }); 

@bennobuilder
Copy link

bennobuilder commented Dec 16, 2023

As the Radix docs state: If you need more flexibility, you can control the component using value/onValueChange props and passing children to SelectValue.

@mammad-arvin
Copy link

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

@amuelrath
Copy link

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.

@shadcn shadcn added the Stale label Feb 29, 2024
@dbersan
Copy link

dbersan commented May 4, 2024

Where is the entire code that works?

@jhelmink
Copy link

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>
                  )}
                />

@shadcn shadcn removed the Stale label Jun 6, 2024
@andrewpap22
Copy link

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.

@shadcn shadcn added the Stale label Jun 25, 2024
@WangLarry
Copy link

#4021 (comment)

@shadcn shadcn removed the Stale label Jun 26, 2024
@fuadelgadi
Copy link

fuadelgadi commented Jul 12, 2024

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

@camillevingere
Copy link

Is there a solution ?

@RDX777
Copy link

RDX777 commented Jul 30, 2024

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>
  )}

@shadcn shadcn added the Stale label Aug 14, 2024
@shadcn
Copy link
Collaborator

shadcn commented Aug 22, 2024

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.

@shadcn shadcn closed this as completed Aug 22, 2024
@yourcasualdev
Copy link

Guys you can parse default values straight into react-hook-form https://github.com/orgs/react-hook-form/discussions/7491#discussioncomment-4942804

typescript const form = useForm({ resolver: zodResolver(Schema), defaultValues: Schema.parse({}), });

When you do it like this, default values will work.

@Shadow7101
Copy link

i solved my problem putting "default Value" and "value" on select tag, thanks for every one his put his comment her

@subhendu-baral
Copy link

If you are using Controlled Form use "value" instead of "defaultValue". If you are using uncontrolled form you may use "defaultValue". Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests