Closed LevaniVashadze closed 7 months ago
This is not the correct way to use react-hook-form.
you should not use useState when working with react-hook-form. You can custom your value at onChange. Your value should be in react-hook-form’s provider.
Thanks for the quick response, I got it working now, I added the t variable to translate the labels to the component and now it works. Without the weird stuff I did. Although it would be nice for the component to store an array of values instead of storing the labels as well, that's why I tried to change it so that I can save arrays of IDs in the DB and then convert them to label | id objects client side.
Also a simple defaultSelectedOptions prop would have been nice, with that I could have achieved the result
<div className="flex flex-wrap gap-1">
<ScrollArea
className={cn("h-full w-full", selected.length < 1 && "hidden")}
>
<div className="flex h-full flex-row flex-nowrap gap-x-1 pb-2">
{selected.map((option) => {
return (
<Badge
key={option.value}
className={cn(
"text-nowrap data-[disabled]:bg-muted-foreground data-[disabled]:text-muted data-[disabled]:hover:bg-muted-foreground",
"data-[fixed]:bg-muted-foreground data-[fixed]:text-muted data-[fixed]:hover:bg-muted-foreground",
badgeClassName,
)}
data-fixed={option.fixed}
data-disabled={disabled}
>
{option.label}
<button
className={cn(
"ml-1 rounded-full outline-none ring-offset-background focus:ring-2 focus:ring-ring focus:ring-offset-2",
(disabled || option.fixed) && "hidden",
)}
onKeyDown={(e) => {
if (e.key === "Enter") {
handleUnselect(option);
}
}}
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
onClick={() => handleUnselect(option)}
>
<X className="h-3 w-3 text-muted-foreground hover:text-foreground" />
</button>
</Badge>
);
})}
</div>
<ScrollBar
orientation="horizontal"
className="h-1.5 *:bg-white/40"
/>
</ScrollArea>
{/* Avoid having the "Search" Icon */}
<CommandPrimitive.Input
{...inputProps}
ref={inputRef}
value={inputValue}
disabled={disabled}
onValueChange={(value) => {
setInputValue(value);
inputProps?.onValueChange?.(value);
}}
onBlur={(event) => {
setOpen(false);
inputProps?.onBlur?.(event);
}}
onFocus={(event) => {
setOpen(true);
triggerSearchOnFocus && onSearch?.(debouncedSearchTerm);
inputProps?.onFocus?.(event);
}}
placeholder={
hidePlaceholderWhenSelected && selected.length !== 0
? ""
: placeholder
}
className={cn(
"ml-2 flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
inputProps?.className,
)}
/>
</div>
On an unrelated note, this might be useful to add, a horizontal scrollbar, needs polishing and adjusting but you get the point
Just giving the value. That would be your default selections.
Or giving the defaultValues
at react-hook-form.
The input will automatically expand when you pick more options over the size.
A scroll area is also a good idea.
As a developer, it's easy to add and control it by giving props. 💪
As a user, I prefer to see all options at one sight rather than scrolling the input box 😅.
I did see that it will grow, but sometimes it grew too much so I either had to limit the amount of tags they can pick or make it scrollable. I also got 2 of these above each other and soon enough they would grow too big
Also I settled for defaultvalues and now store the labels as translation strings and then translate them inside the component by the added "t" prop
Uncaught (in promise) TypeError: elm.focus is not a function focus index.esm.mjs:472 _focusInput index.esm.mjs:1979 iterateFieldsByAction index.esm.mjs:694 _focusError index.esm.mjs:2185 handleSubmit index.esm.mjs:2233 React 23 renderReactElement index.js:421 doRender index.js:579 render index.js:596 hydrate index.js:724 pageBootrap page-bootstrap.js:24