React JSX - inject br tag in loop - reactjs

How can I add a tag between selected options in jsx?
<Select
labelId="demo-mutiple-checkbox-label"
id="demo-mutiple-checkbox"
multiple
value={preferences}
onChange={handleChangePreferences}
input={<Input />}
renderValue={(selected) => selected.join(<br />)}
// MenuProps={MenuProps}
style={{width: "100%", whiteSpace: "break-spaces"}}
>
I've tried br , \n, "\n" - i can't find a way that works.
The Material UI docs show an example with a comma - I'm trying to use a br

Update the Select component to this. E.g https://codesandbox.io/s/material-demo-40jg3
<Select
labelId="demo-mutiple-checkbox-label"
id="demo-mutiple-checkbox"
multiple
value={personName}
onChange={handleChange}
input={<Input />}
renderValue={selected => (
<>
{selected.map(value => (
<>
{value}
<br />
</>
))}
</>
)}
MenuProps={MenuProps}
>

Related

stopPropogation not working consistently in React

I am working with 2 dropdown menus using stopPropogation to prevent the menu shifting up and down when items are checked and unchecked.
One menu works great but the other is still jumping up and down when checking and unchecking items, although I am confident that I'm using stopPropogation in the same way for both instances. I am wondering what I am doing wrong in the faulty dropdown menu that's causing this issue.
Working dropdown menu:
return (
<div onClick={(e) => {
e.stopPropagation();
}}>
<FormControl
variant="outlined"
size="small"
className={classes.formControl}
>
<InputLabel id="demo-mutiple-checkbox-label" align="left" margin="dense">
Select Models
</InputLabel>
<Select
multiple
labelId="demo-mutiple-checkbox-label"
label="SelectModels"
value={modelIds}
onChange={handleChange}
renderValue={(selected) =>
selected
.map(
(id) =>
deviceModelData.find((model) => model.alg_id === id).alg_name
)
.join(', ')
}
MenuProps={MenuProps}
className={classes.rootSelect}
>
{deviceModelData.map((model, index) => (
<MenuItem key={model.alg_id} value={model.alg_id}>
<Checkbox checked={modelIds.includes(model.alg_id)} />
<ListItemText primary={model.alg_name} />
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
Problematic dropdown menu:
return (
<div
onClick={(e) => {
e.stopPropagation();
}}
>
<FormControl
variant="outlined"
size="small"
className={classes.formControl}
>
<InputLabel id="demo-mutiple-checkbox-label">Select Classes</InputLabel>
<Select
labelId="demo-mutiple-checkbox-label"
label={label}
id="demo-mutiple-checkbox"
multiple
value={classIds}
onChange={handleClassIdsChange}
renderValue={(selected) =>
selected
.map((id) => marketplaceModelClasses[id].original_label)
.join(', ')
}
MenuProps={MenuProps}
>
{allClassIds.map((classId) => {
return (
<MenuItem key={classId} value={classId}>
<Checkbox
value={classId}
checked={classIds.indexOf(classId) > -1}
/>
<ListItemText
primary={marketplaceModelClasses[classId].original_label}
/>
</MenuItem>
);
})}
</Select>
</FormControl>
</div>
);
}

Passing Formik input values in nested forms using Material UI

I'm currently having problems when using Formik with MaterialUI forms. Specifically,
I am having trouble passing Formik input values in nested forms using Material UI and having a small issue where Formik.handleChange is changing the value from number to string.
I have multiple forms that are split with Stepper component in Material UI. Since I am still learning, I tried to wrap Formik on one of the steps (later on I am going to wrap the whole stepper). Here's how it looks:
{activeStep === 0 && (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{formik => (
<form onSubmit={formik.handleSubmit}>
<div className="col-xl-6">
<Portlet fluidHeight>
<PortletHeader title="Incident Type" />
<PortletBody>
<IncidentSelect formik={formik} />
</PortletBody>
</Portlet>
</div>
</form>
)}
</Formik>
)}
The problem is inside the IncidentSelect form, Formik handleChange does not seem to change the selected radioButton. When I inspected with React Developer Tools in Chrome it seems that Formik.handleChange is changing the value from 0 to "0". How do I fix this?
Also, following the tutorial, I'm unsure how I can abstract my components? Note that DateTimePicker is using material-ui/pickers. I'm not sure how I am going to pass the value to Formik.
Any help is appreciated.
Thanks
function IncidentSelect(props) {
const [value, setValue] = React.useState("female");
const handleRadioChange = e => {
console.log(props.formik.getFieldProps("incidentType"));
setValue(e.target.value);
};
return (
<>
<FormControl component="fieldset">
<FormLabel component="legend" required>
Incident Type:
</FormLabel>
<RadioGroup
aria-label="Incident Type"
name="incidentType"
value={value}
onChange={handleRadioChange}
{...props.formik.getFieldProps("incidentType")}
>
<FormControlLabel
value={0}
control={<Radio />}
label="Injury To Guest"
/>
<FormControlLabel
value={1}
control={<Radio />}
label="Injury To Worker"
/>
<FormControlLabel
value={2}
control={<Radio />}
label="Incident / Accident"
/>
<FormControlLabel
value={3}
disabled
control={<Radio />}
label="OSH / Kids Camp"
/>
</RadioGroup>
</FormControl>
<DateTimePicker
label="Signed Date"
variant="outlined"
className={classes.margin}
value={selectedDate}
onChange={handleDateChange}
/>
</>
);
}
As stated in the tutorial, it is easier to abstract the component that you want to use. Giving you chances to reuse them later in your application and more readable code.
Formik provides you with useFields API to get the props of the field via hooks. useFields is looking for the name props of your component to find the corresponding field.
Thus RadioGroup from MaterialUI can be extracted as follows:
export const IncidentRadioButton = ({ options, ...props }) => {
const [field, meta] = useField(props);
return (
<>
<RadioGroup {...field} {...props}>
{options.map((option, index) => (
<FormControlLabel
control={<Radio />}
label={option.name}
value={option.value}
key={index}
/>
))}
</RadioGroup>
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</>
);
};
Then you can use the options prop to put your data accordingly

Material UI select and autocomplete box not lined up

Screenshot of misaligned drop-down boxes
Hi! I'm a beginner ReactJS engineer. I added 2 drop-down boxes from material UI, the left box is the Autocomplete from materialui/labs and the right box is the Select from materialui/core. They're both placed in the same component with the same styling applied to it, but the Autocomplete is slightly off. Is there a simple fix to this misalignment?
<AutocompleteComponent
formStyle={{ width: 200 }}
label={'Build'}
options={builds}
value={selectedBuild}
handleChange={handleFilterSelectChange('selectedBuild')} />
<SelectComponent
formStyle={{ width: 120 }}
label={'Sheet Layout'}
options={sheetLayouts}
value={selectedSheetLayout}
handleChange={handleFilterSelectChange('selectedSheetLayout')} />
For select component:
const SelectComponent = props => {
return (
<FormControl
className={className}
required={required}
error={error}
margin={margin}
style={formStyle}
>
<InputLabel>{label}</InputLabel>
<Select
inputRef={inputRef}
value={value}
style={style}
onChange={handleChange}
disabled={disabled}
onClick={onClick}
onFocus={onFocus}
onBlur={onBlur}
>
{excludeNone ? null : (
<MenuItem value="">
<em>{noneLabel ? noneLabel : "None"}</em>
</MenuItem>
)}
{optionsExist(options)}
</Select>
{helperText ? <FormHelperText>{helperText}</FormHelperText> : null}
</FormControl>
);
};
For the autocomplete component:
class AutocompleteComponent extends React.Component {
render() {
return (
<FormControl
className={className}
required={required}
error={error}
margin={margin}
style={formStyle}
>
<Autocomplete
style={style}
disabled={disabled}
onClick={onClick}
onFocus={onFocus}
onBlur={onBlur}
options={options}
getOptionLabel= {option => option.label && option.label.toString()}
id="auto-complete"
autoComplete
includeInputInList
renderInput={params => (
<TextField
{...params}
label="Builds"
margin="normal"
fullWidth
position="center"
/>
)}
renderOption={(option, { inputValue }) => {
const matches = match(option.label, inputValue);
const parts = parse(option.label, matches);
return (
<div>
{parts.map((part, index) => (
<span
key={index}
style={{ fontWeight: part.highlight ? 700 : 400 }}
>
{part.text}
</span>
))}
</div>
);
}}
/>
{helperText ? <FormHelperText>{helperText}</FormHelperText> : null}
</FormControl>
);
}
}
Thanks!

How to show an inputlabel/placeholder/label permanently?

I'm using the multi-select with checkboxes from material ui v4. The provided default settings display an array of 'SELECTED' values. renderValue={selected => selected.join(', ')}. However, I would like to remove this function and only display a permanent label. It seems that the display value is being tied to the value of the component itself. Does anybody knows how to work around this?
<FormControl className={classes.formControl}>
<InputLabel htmlFor="select-multiple-checkbox">Tag</InputLabel>
<Select
multiple
value={personName}
onChange={handleChange}
input={<Input id="select-multiple-checkbox" />}
renderValue={selected => selected.join(', ')}
MenuProps={MenuProps}
>
{names.map(name => (
<MenuItem key={name} value={name}>
<Checkbox checked={personName.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
Are you saying that you don't want any indication of what the selected values are?
If so, below is one way of doing that:
<FormControl className={classes.formControl}>
<InputLabel shrink={false} htmlFor="select-multiple-checkbox">
Tag
</InputLabel>
<Select
multiple
value={personName}
onChange={handleChange}
input={<Input id="select-multiple-checkbox" />}
renderValue={() => (
<span dangerouslySetInnerHTML={{ __html: "​" }} />
)}
MenuProps={MenuProps}
>
{names.map(name => (
<MenuItem key={name} value={name}>
<Checkbox checked={personName.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
<InputLabel shrink={false}
This prevents the label from shrinking and moving up when the Select is focused.
renderValue={() => (<span dangerouslySetInnerHTML={{ __html: "​" }} />)}
This causes a zero-width space to be rendered as the "selected values". This ensures that the height doesn't collapse (which is what happens if you just return empty string) while still allowing the label to be displayed.

Add element inside TextField component - Material UI

I want to create input element which will have select property but also to be able to write custom text in it. I'm using React and Material-UI.
Is it possible to add element inside TextField component (inside div just below input) in Material-UI.
Currently:
Usluga
grupni
Pos
....
With added element:
<div class="MuiFormControl-root-142 ...>
<label class="MuiFormLabel-root-151 ...>Usluga</label>
<div class="MuiInput-root-156 ...>
<input aria-invalid="false" ... list="services" value="">
<datalist id="services">
<li tabindex="-1" ...>grupni<span class="MuiTouchRipple-root-82"></span>
</li>
<li tabindex="-1" ...>Pos<span class="MuiTouchRipple-root-82"></span>
</li>
....
</div>
</div>
React currently:
<TextField
id="service"
label="Usluga"
className={classes.textField}
margin="normal"
onChange={handleChange}
inputProps={{
list: "services"
}}
/>
<datalist id="services">
{
services.map(option => (
<MenuItem key={option.id} value={option.service}>
{ option.service }
</MenuItem>
))
}
</datalist>
If that's not possible, what is the other way to make this?
You can try this method, it worked for me :)
<TextField
required
id='password'
label='Password'
onChange={handleOnChange}
type={toggle.passwordVisibility ? 'text' : 'password'}
InputProps={{
endAdornment: (
<InputAdornment position='end'>
<IconButton
aria-label='toggle password visibility'
onClick={handlePasswordVisibility}
onMouseDown={handleMouseDownPassword}>
{toggle.passwordVisibility && <Visibility />}
{!toggle.passwordVisibility && <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
You can do it this way: InputProps={{ endAdornment: <YourComponent /> }}
https://material-ui.com/api/input/
You can try this method, it worked for me :)
<TextField
variant="outlined"
name="rfc"
size={'small'}
label="RFC"
InputProps={{
endAdornment: (
<datalist id="rfc">
<option value="XAXX010101000"></option>
<option value="XEXX010101000"></option>
</datalist>
),
inputProps: {
list: "rfc"
}
}}
/>

Resources