I have created a select component using react-select. I need to append a badge to the option who's available value is false. I have achieved it using -
const formatOptionLabel = ({ code, name, available }) => (
<div className="ds-select-distibutor-step-container format-option" style={{ display: "flex", cursor:"none" }}>
<div>{name}</div>
{!available ?
<div className="format-label" style={{ borderRadius: "12px" ,marginLeft: "auto", color: "#fff" , backgroundColor: "#aaa", padding: "2px 10px", fontSize:"12px"}}>
<span>Coming Soon</span>
</div>
: ''}
</div>
);
Following json comes at run time, which I map and use as options-
const options= [
{code:"abc",name:"abc",rank:0,available:true},
{code:"xyz",name:"xyz",rank:0,available:false},
{code:"pqr",name:"pqr",rank:0,available:true}]
And following is my custom select component
<Field
id="selectedDistributor"
name="selectedDistributor"
component={customSelect}
options={sortBy(options, 'name').map(({ code, name, available}) => ({ code, name, available }))}
formatOptionLabel={formatOptionLabel}
className="select-step"
placeholder="abc"
touched={false}
defaultValue="abc"
requiredField
>
</Field>
<FieldWrapper
label={label}
requiredField={requiredField}
touched={touched}
forId={inputId}
>
<Select
{...input}
id={inputId}
disabled={isEditMode || disabled}
onChange={value => input.onChange(value.code)}
formatOptionLabel={formatOptionLabel}
options={options}
placeholder={placeholder}
value={input.code}
className={`input-components-select ${className}`}
>
</Select>
</FieldWrapper>
enter code here
Everything is almost working but when I select the option, the background of all the options turns into blue, I tried making changes and found that if I pass the 'value' as a key of JSON instead of 'name' in the option this error goes away. But I can't use it since the json is coming from the backend and its dynamic.
Could anybody please suggest what should be done so that the background doesn't change? I have attached images for reference
first time
after selecting
I faced the same problem and I found that you need to declare a function getOptionValue as the Select's props. In your example, it should be like this
<Select
{...input}
id={inputId}
disabled={isEditMode || disabled}
onChange={value => input.onChange(value.code)}
formatOptionLabel={formatOptionLabel}
options={options}
placeholder={placeholder}
value={input.code}
getOptionValue={(option) => option.code} // changes here!!!
className={`input-components-select ${className}`}
>
</Select>
This function is used for comparison to highlight the currently selected option in the list. You can check more details in the discussion here
https://github.com/JedWatson/react-select/issues/3388
Related
While building a user interface with a few inputs, I decided to migrate the base input components to form a single component I can use, while that's not really the problem. Here's the code for it. For easy and memorable use for Inputs.
import {
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
Input,
} from "#chakra-ui/react";
const DefaultInput = ({
isInvalid,
label,
helperText,
errorMessage,
...otherProps
}) => {
return (
<FormControl isInvalid={isInvalid}>
{label && <FormLabel>{label}</FormLabel>}
<Input
variant="outline"
padding="25px 10px"
margin="10px 0px"
border={"0px"}
{...(isInvalid && { border: "0px" })}
{...otherProps}
/>
{!isInvalid ? (
<FormHelperText>{helperText}</FormHelperText>
) : (
<FormErrorMessage>{errorMessage}</FormErrorMessage>
)}
</FormControl>
);
};
export default DefaultInput;
Used it like this but it doesn't seem to take notice of the "max" property.
<DefaultInput
value={custom.credits}
isInvalid={creditsError}
helperText={"Minimum of 50 Credits."}
errorMessage={"Please enter a valid number above 50."}
maxW={isNotSmallerScreen ? "50%" : "70%"}
fontSize={!isNotSmallerScreen ? "12px" : "16px"}
onChange={handleCustomCredit}
type="number"
placeholder="Enter Credits"
name="credits"
max="5000"
/>
I've also tried manually declaring the "max" and "type" within the component I created but still nothing.
.....
<Input
variant="outline"
padding="25px 10px"
margin="10px 0px"
border={"0px"}
max="5000"
type="number"
{...(isInvalid && { border: "0px" })}
{...otherProps}
/>
.....
This is actually a browser quirk and not related to Chakra. max HTML5 attribute won't actually restrict you from typing larger numbers until you submit the containing form. If you want to limit it on the fly you have to build out your own function.
Unless you aren't seeing anything on submit either? See this example of what you should see https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_max_min.
I want to display image with name in react-dropdown-select package. I acheive using below code, but the problem is searchable not working.
I want display image with name and id, need to search name also
This is my multi react-dropdown-select package code
<Select isClearable={false}
placeholder={"Select Mates"}
styles={this.customStyles}
menuPortalTarget={document.querySelector('body')}
value={this.state.selectedOption}
onChange={this.handleChange}
selectedValue={true}
hideSelectedOptions={false}
options={Dropdownlist.map(e => ({
label: <span><img src={e.image} /> {e.name} </span>, value: e.id}))}
isMulti
theme={theme => ({
...theme,
colors: {
...theme.colors,
neutral50: 'white',
},
})}
/>
Any one help me to solve my problem
thanks in advance
I need to change the value of the input field to whatever value of the select field has changed.
If "Fire" is selected in the select field, then the input field needs to change to "Fire" as well.
This works when using the value in the input field and assigning the state of select to it.
Working Code:
const [type, setType] = React.useState("");
<Select
style={{
width: 120
}}
onChange={(value) => setType(value)}
>
<Option value="fire">Fire</Option>
<Option value="water">Water</Option>
<Option value="wind">Wind</Option>
</Select>
<Input
style={{
width: 120
}}
placeholder="Enter Type"
value={type}
/>
The above code works, but using inside a Form, it doesn't.
Code:
const Demo = () => {
const [type, setType] = React.useState("");
return (
<Form onFinish={onSubmit}>
<Form.Item name="floorType">
<Select
style={{
width: 120
}}
onChange={(value) => setType(value)}
>
<Option value="fire">Fire</Option>
<Option value="water">Water</Option>
<Option value="wind">Wind</Option>
</Select>
</Form.Item>
<Form.Item name="floorName">
<Input
style={{
width: 120
}}
placeholder="Enter Type"
value={type}
/>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
style={{
width: 120
}}
>
Submit
</Button>
</Form.Item>
</Form>
);
};
The value isn't set in the input field.
UI Library used : Antd https://ant.design/components/form/
Codesandbox link : https://codesandbox.io/s/basic-usage-antd-4-21-6-forked-ckxgsy?file=/demo.js
Fixed fork
I based this fix on the Antd Form > Form Methods example, which shows how to update a form field when another one changes.
The problem seems to be you're using Input>value instead of letting the Antd Form handle the form state.
The problem arises when adding Form.Item>name, because in this way the Form itself handles the child input value using a hidden state object where the keys are the Form.Item names and the initial values are the ones you can optionally define inside Form>initialValues prop.
So, if you want to avoid having the form manage the state, you should also avoid using Form.Item>name prop and manage all form state yourself (but missing out on many of the advantages of the Antd form).
In fact this should be avoided.
Explanation of the fix
In the fork, the form manages the state, and the setFieldsValue method is used to update the floorName value (aka your Input).
Changes
Removed the value prop from the input
<Input
style={{
width: 120
}}
placeholder="Enter Type"
// Remove the prop value from the input and let the form handle it
/>
Add a form reference (using Form.useForm)
const Demo = () => {
// Get a form reference
const [form] = Form.useForm();
return (
<Form
form={form}
...
Update the Select onChange using the form method setFieldsValue instead of the setType setter
<Select
style={{
width: 120
}}
onChange={(value) => {
// Set New Form Value for Form.Item > name = 'floorName'
form.setFieldsValue({ floorName: value });
// Using the Form.Item 'name' as object key when updating
}}
>
After all, the Antd Form is an
High performance Form component with data scope management
so you shouldn't try to handle the form state yourself (especially when Form.Item>name is specified for your fields).
Here is an example of my component, wrapped into Controller
<div className="mt-1">
<Controller
control={control}
name="selectedBirthMonth"
defaultValue={selectedMonth}
render={({ field }) => (
< SelectBirthMonth
field={field}
startYear={startYear}
selectedYear={selectedYear}
months={months}
value={selectedMonth}
reducedMonths={reducedMonths}
onChange={useEffect(() => monthSelect(field.value)), [selectedMonth]}/>
)}
/>
</div>
For now I am just trying to reset it with a button. Later I'd love to conditionally reset, depending on the value in a sibling component. Would be great to get it work with the button in the first place:
<input
style={{ display: "block", marginTop: 20 }}
type="button"
onClick={() =>
reset(selectedBirthMonth)
}
value="Reset with values"
/>
I get en error: selectedBirthMonth is not defined. Bassicaly, what I am aming for,on click, the whole component goes to default / a state it had when first rendered. What am I missing?
reset didn't do the job somehow, but setValue did. However I am setting to a value, not to the original state after first render, but in my case it's same.
<input
style={{ display: "block", marginTop: 20 }}
type="button"
onClick={() =>
etValue('selectedBirthMonth', lastAvaliableMonth)
}
value="Reset with values"
/>
I have a question about rendering errors when using Formik#1.5.7 to create forms in React.
I am trying to figure out how to properly render different styles for my input based on whether or not the input has been touched and has errors.
{({ values, error, touched }) => (
<Form>
<Field name="Lawn" type="text">
{({ field, form }) => (
<Input
style={form.touched.Lawn && form.errors.Lawn ?
{ style } : { styleError }}
{...field}
type="text"
placeholder="Lawn Details"
/>
)}
</Field>
const style = {
margin: '1em 0em',
fontSize: '1.5em',
backgroundColor: 'white',
};
const styleError = {
margin: '1em 10em',
fontSize: '1.5em',
};
I believe my error has to do with not properly accessing the touched and error states in the form.
Any help would be very appreciated.
You're close, you just incorrectly passed style and styleError. They should not be surrounded with braces (and they're also backwards because the error formatting will show when there is no error and vice versa).
<Input
style={form.touched.Lawn && form.errors.Lawn ? styleError : style}
{...field}
type="text"
placeholder="Lawn Details"
/>
Here's a full example.