How to display data from html response body on textfield or textArea in material UI reactjs? - reactjs

I have a form. On clicking the 'Evaluate' button, I send a post request. The response of this request is JSON, which I need to display in textField named Output.
How to display data in 'Output' textField?
I just need to display data(which is json in this case) to the text field.
My text field looks like this:
const MyTextField = ({select, values, nullable, min, max, helpertext, ...props}) => {
const [field, meta] = useField(props);
return (
<TextField
select={!!select}
variant="outlined"
margin="dense"
//{...field}
//defaultValue={meta.initialValue}
value={field.value}
error={meta.touched && meta.error}
helperText={(meta.touched && meta.error) ? meta.error : helpertext}
onChange={field.onChange}
onBlur={field.onBlur}
InputProps={{inputProps: {min: min, max: max}}}
{...props}
>
{
values && nullable && values instanceof Array && <MenuItem ><em>None</em></MenuItem>
}
{
values && values instanceof Array && values.map((value, index) => {
return <MenuItem key={value} value={value}>{value}</MenuItem>
})
}
</TextField>
);
};
and form looks like this
return (
<Container fluid className="main-content-container px-4">
<Row noGutters className="page-header py-4">
<PageTitle sm="12" title="Transformer Tester Tool" subtitle="" className="text-center"/>
</Row>
<Paper id="connPageRoot" className={classes.testerRoot}>
<Formik onSubmit={submitEvaluate} initialValues={request}>
<Form>
<div>
<MyTextField
variant="outlined"
margin="dense"
id="json2JsonTransformationConfigDto.template"
name="json2JsonTransformationConfigDto.template"
label="JSLT template"
multiline={true}
rowsMax={4}
fullWidth={true}/>
</div>
<div>
<MyTextField
variant="outlined"
margin="dense"
id="inputs.0"
name="inputs.0"
label="Json payload to be tested"
multiline={true}
rowsMax={4}
fullWidth={true}
/>
</div>
<div className={classes.connPageButton}>
<Button type={"submit"} color="primary" variant="contained">Evaluate</Button> </div>
<div>
<MyTextField
variant="outlined"
margin="dense"
id="outputs.0"
name="outputs.0"
label="Output"
value={result}
multiline={true}
rowsMax={4}
fullWidth={true}
/>
</div>
</Form>
</Formik>
</Paper>
</Container>
);

Related

React Application form data with image uploading field cannot POST to my backend api

First I am trying to post my form data without an image then that data is passed to the backend successfully. then I try to send an image to the backend with form data and then I got an error. image uploading field is a not required field. how I pass the image to the backend with form data.
This is my basic info tab image uploading field
<Grid item xs={6} md={3} sm={4}>
<Controller
name="avatar"
id="avatar"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-4 mb-8"
type="file"
onChange={(event) => {
// console.log(event.target.files[0]);
setSelectedImage(event.target.files[0]);
}}
autoFocus
value={selectedImage}
variant="outlined"
size="small"
fullWidth
/>
)}
/>
</Grid>
this is my user.js file return
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<Root
header={<UserHeader />}
contentToolbar={
<Tabs
value={tabValue}
onChange={handleTabChange}
indicatorColor="primary"
textColor="primary"
variant="scrollable"
scrollButtons="auto"
classes={{ root: 'w-full h-64' }}
>
<Tab className="h-64" label="Basic Info" />
// <Tab className="h-64" label="User Images" />
</Tabs>
}
content={
<div className="p-16 sm:p-16 max-w-2xl">
<div className={tabValue !== 0 ? 'hidden' : ''}>
<BasicInfoTab />
</div>
<div className={tabValue !== 1 ? 'hidden' : ''}>
<ImagesTab />
</div>
{/* <div>
<input type="file" name="file_upload" onChange={onFileChage}/>
</div>
<div>
<button>Submit Data</button>
</div>*/}
</div>
}
innerScroll
/>
</form>
</FormProvider>
);
}
This is my error

Dynamically adding or removing items within a react-hook-forms form and registering the inputs?

I'm trying to implement a rather complicated form that has and date picker and input which the user can add multiple of (or delete). That data then gets added to the overall form on submit. How do I get react-hook-forms to register that little dynamic faux form within the real form?
Here's the faux form inputs:
<AddPackagesStyle>
<Label htmlFor="addedPackages" label="Add Packages" />
<DatePicker
id="dateRange"
selected={startDate}
selectsRange
startDate={startDate}
endDate={endDate}
placeholderText="select dates"
onChange={onDateChange}
/>
<PackageInput
id="PackageSelect"
placeholder="Select Package"
type="text"
value={name}
// #ts-ignore
onChange={(e) =>
// #ts-ignore
setName(e.target.value)
}
/>
<ButtonContainer>
<button type="button" onClick={clearAll}>
Clear
</button>
<button
type="button"
// #ts-ignore
onClick={addPackage}
>
Add
</button>
</ButtonContainer>
</AddPackagesStyle>
These entries get added to an array in a useState hook:
const [addedPackages, setAddedPackages] = useState<any[]>([])
Then this gets rendered in JSX as the add packages:
<ContentSubscriptionWrapper>
{addedPackages.length !== 0 &&
addedPackages.map((addedPackage, idx) => (
// #ts-ignore
<>
<ContentSubscriptionColumn>
{addedPackage.name && addedPackage.name}
</ContentSubscriptionColumn>
<ContentSubscriptionColumn>
{addedPackage.startDate &&
addedPackage.startDate.toString()}
</ContentSubscriptionColumn>
<ContentSubscriptionColumn>
{addedPackage.endDate && addedPackage.endDate.toString()}
</ContentSubscriptionColumn>
<button type="button" onClick={() => removePackage(idx)}>
X
</button>
</>
))}
</ContentSubscriptionWrapper>
So before the form gets submitted, the 'add packages' has to be set. Where do I add the {...register} object to add to the larger form object for submission?
const {
control,
register,
handleSubmit,
formState: { errors },
} = useForm<any>()
const onSubmit = (data: any) => {
console.log(data)
}
I created a CodeSandbox trying to reproduce your use case and used Material UI to get it done quickly, but you should get the idea and can modify it with your own components.
you should let RHF handle all the state of your form
use RHF's useFieldArray for managing (add, remove) your packages/subscriptions - there is no need to use watch here
use a separate useForm for your <AddPackage /> component, this has the benefit that you will have form validation for this sub form (in case it should be a requirement that all fields of <AddPackage /> need to be required) - i added validation in the demo to demonstrate this
AddPackage.tsx
export const AddSubscription: React.FC<AddSubscriptionProps> = ({ onAdd }) => {
const {
control,
reset,
handleSubmit,
formState: { errors }
} = useForm<Subscription>({
defaultValues: { from: null, to: null, package: null }
});
const clear = () => reset();
const add = handleSubmit((subscription: Subscription) => {
onAdd(subscription);
clear();
});
return (
<Card variant="outlined">
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Grid container spacing={1} p={2}>
<Grid item container spacing={1} xs={12}>
<Grid item xs={6}>
<Controller
name="from"
control={control}
rules={{ required: "Required" }}
render={({ field }) => (
<DatePicker
{...field}
label="From"
renderInput={(params) => (
<TextField
{...params}
fullWidth
error={!!errors.from}
helperText={errors.from?.message}
/>
)}
/>
)}
/>
</Grid>
<Grid item xs={6}>
<Controller
name="to"
control={control}
rules={{ required: "Required" }}
render={({ field }) => (
<DatePicker
{...field}
label="To"
renderInput={(params) => (
<TextField
{...params}
fullWidth
error={!!errors.to}
helperText={errors.to?.message}
/>
)}
/>
)}
/>
</Grid>
</Grid>
<Grid item xs={12}>
<Controller
name="package"
control={control}
rules={{ required: "Required" }}
render={({ field: { onChange, ...field } }) => (
<Autocomplete
{...field}
options={packages}
onChange={(e, v) => onChange(v)}
renderInput={(params) => (
<TextField
{...params}
label="Package"
fullWidth
error={!!errors.package}
helperText={errors.package && "Required"}
/>
)}
/>
)}
/>
</Grid>
<Grid item xs={12}>
<Stack spacing={1} direction="row" justifyContent="end">
<Button variant="outlined" onClick={clear}>
Clear
</Button>
<Button variant="contained" onClick={add} type="submit">
Add
</Button>
</Stack>
</Grid>
</Grid>
</LocalizationProvider>
</Card>
);
};
Form.tsx
export default function Form() {
const { control, handleSubmit } = useForm<FormValues>({
defaultValues: {
seats: "",
addOns: false
}
});
const { fields, append, remove } = useFieldArray({
control,
name: "subscriptions"
});
const onSubmit = (data) => console.log("data", data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Box display="flex" justifyContent="end" gap={1}>
<Button variant="outlined">Cancel</Button>
<Button variant="contained" type="submit">
Save
</Button>
</Box>
</Grid>
<Grid item xs={12}>
<Controller
name="seats"
control={control}
render={({ field }) => (
<TextField {...field} fullWidth label="Seats" />
)}
/>
</Grid>
<Grid item xs={12}>
<AddSubscription onAdd={append} />
</Grid>
<Grid item xs={12}>
<List>
{fields.map((field, index) => (
<ListItem
key={field.id}
secondaryAction={
<IconButton
edge="end"
aria-label="delete"
onClick={() => remove(index)}
>
<DeleteIcon />
</IconButton>
}
>
<ListItemText
primary={field.package.label}
secondary={
<span>
{formatDate(field.from)} - {formatDate(field.to)}
</span>
}
/>
</ListItem>
))}
</List>
</Grid>
<Grid item xs={12}>
<Controller
name="addOns"
control={control}
render={({ field: { value, onChange } }) => (
<FormControlLabel
control={<Checkbox checked={!!value} onChange={onChange} />}
label="Add-ons"
/>
)}
/>
</Grid>
</Grid>
</form>
);
}

Why can't I get values of Date and Text Area in Formik?

I am using Formik and Yup for a form control in React application. I use also Semantic UI. In the application, when I click the submit button, whereas I can read the values from FormField elements and see them on Console, I can not get the value of Date and Text Area elements and they appear blank on Console. How can I solve this out?
Here I define the intial values.
const initialValues = {
jobTitle: { id: "" },
deadline: "",
description: "",
};
Then here I try to get the values from form element
return (
<div>
<Card fluid>
<Card.Content>
<Card.Header>Create A New Job Ad</Card.Header>
<Divider inverted />
<Formik
initialValues={initialValues}
validationSchema={jobAdCreateSchema}
onSubmit={(values) => {
handleSubmit(values);
}}
>
{({ values, setFieldValue }) => (
<div>
<pre>{JSON.stringify(values, undefined, 2)}</pre>
<Form className="ui form">
<FormField>
<label>Job Title</label>
<Dropdown
selection
placeholder="Select a Job Title"
name="jobTitle"
fluid
options={jobTitleOption}
value={values.jobTitle.id}
onChange={(_, { value }) =>
setFieldValue("jobTitle.id", value)
}
/>
</FormField>
<FormField>
<label>Application Deadline</label>
<input
name="deadline"
style={{ width: "100%" }}
type="date"
placeholder="Application Deadline"
value={values.deadline}
onChange={formik.handleChange}
/>
</FormField>
<FormField>
<label>Job Description</label>
<TextArea
name="description"
placeholder="Job Description"
style={{ minHeight: 100 }}
value={values.description}
onChange={formik.handleChange}
/>
</FormField>
<FormField>
<Button color="green" type="submit">
Submit
</Button>
</FormField>
</Form>
</div>
)}
</Formik>
</Card.Content>
</Card>
</div>
);
formik isn't defined, so your assigning an onChange function that doesn't exist.
Destructure handleChange from the argument, then assign it to the inputs like so:
{({ values, setFieldValue, handleChange }) => (
//...
<input
name="deadline"
style={{ width: "100%" }}
type="date"
placeholder="Application Deadline"
value={values.deadline}
onChange={handleChange}
/>
)}
Live demo

Change of input value with state in React JS

I am having 3 text boxes in which users enter values alongwith that I have 3 sliders for which the value is set based on calculation of percentage from the entered values. My problem is I also want to change the text box values based on calculation formulas. So the text box I want them to reflect values with calculation as the slider values change plus user can also type in values.For eg for first textbox I want to calculate value inside with (total-b-c). So with changes in slider values of percentages the values in textboxes should also change. I am unable to do that now-
Here is some supporting code for the same-
const [userValues, setUserValues] = useState({
a: '0',
b: '0',
c: '0',
});
const handleInputChange = (event) =>{
setUserValues({ ...userValues, [event.target.name]: event.target.value });
}
Textboxes-
<div className="container1">
<div className="headingsleft">Enter number of <br></br> invoices</div>
<div>
<h4 style={{fontWeight:500, marginLeft:30,fontSize:19}}>a Invoices</h4>
<br></br>
<br></br>
<TextField label="p.a." type="number" name="a" size="small" className={classes.root} inputProps={{ min: "0" }} variant="outlined" value={userValues.nonedinumber} onChange={handleInputChange} required error={userValues.a=== ""} helperText={userValues.a=== "" ? 'Required' : ' '} ></TextField>
</div>
<div>
<h4 className="headings">b Invoices</h4>
<br></br>
<br></br>
<TextField label="p.a." type="number" name="b" size="small" className={classes.root} inputProps={{ min: "0" }} variant="outlined" value={userValues.b} onChange={handleInputChange} required error={userValues.b=== ""} helperText={userValues.b=== "" ? 'Required' : ' '}/>
</div>
<div>
<h4 style={{fontWeight:500, marginLeft:30,fontSize:19}}>cInvoices</h4>
<br></br>
<br></br>
<TextField label="p.a." type="number" name="c" size="small" className={classes.root} inputProps={{ min: "0" }} variant="outlined" value={userValues.c} onChange={handleInputChange} required error={userValues.c=== ""} helperText={userValues.c=== "" ? 'Required' : ' '}/>
</div>
<div>
<h4 style={{fontWeight:500, marginLeft:30,fontSize:19}}>Total Invoices</h4>
<br></br>
<br></br>
<TextField label="p.a." type="number" size="small" id="total" value={total} disabled variant="outlined" />
</div>
</div>
code for the slider-
const Inputaftercalculate = (props) => {
const classes = useStyles();
return (
<div>
<div className="container2">
<div className="headingsleft">Percentage Distribution
</div>
<div >
<br></br>
<br></br>
<Typography className={classes.slider} id="discrete-slider-always" gutterBottom>
</Typography>
<Slider
defaultValue={20}
getAriaValueText={valuetext}
aria-labelledby="discrete-slider-always"
step={10}
marks={marks}
valueLabelDisplay="on"
value={props.a}
disabled
/>
</div>
<div>
<br></br>
<br></br>
<Typography className={classes.slider} id="discrete-slider-always" gutterBottom>
</Typography>
<Slider
defaultValue={20}
getAriaValueText={valuetext}
aria-labelledby="discrete-slider-always"
step={10}
marks={marks}
valueLabelDisplay="auto"
value={props.b}
/>
</div>
<div>
<br></br>
<br></br>
<Typography className={classes.slider} id="discrete-slider-always" gutterBottom>
</Typography>
<Slider
defaultValue={1}
getAriaValueText={valuetext}
aria-labelledby="discrete-slider-always"
step={10}
marks={marks}
valueLabelDisplay="auto"
value={props.c}
/>
</div>
</div>
</div>
How can I make the input textboxes adjust inside values based on changes in slider values and also let users input in the textbox whenever they need to change values?
First you got get the value and it respective key from the event, then expand it and finally assign the value to the respective key name as shown bellow.
const handleInputChange = e => { const {name, value} = e.target; handleInputChange({ ...userValues, [name]: value, }) }

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!

Resources