Help me to solve , need to be label as place holder in formik react js
the code as follows
import * as React from 'react';
import {render} from 'react-dom';
import {Formik, Field, Form} from 'formik';
import {
Button,
LinearProgress,
MenuItem,
FormControl,
InputLabel,
FormControlLabel,
} from '#material-ui/core';
import MuiTextField from '#material-ui/core/TextField';
import {
fieldToTextField,
TextField,
TextFieldProps,
Select,
Switch,
} from 'formik-material-ui';
interface Values {
email: string;
}
const ranges = [
{
value: 'none',
label: 'None',
},
{
value: '0-20',
label: '0 to 20',
},
{
value: '21-50',
label: '21 to 50',
},
{
value: '51-100',
label: '51 to 100',
},
];
const UppercasingTextField = (props: TextFieldProps) => (
<MuiTextField
{...fieldToTextField(props)}
onChange={event => {
const {value} = event.target;
props.form.setFieldValue(
props.field.name,
value ? value.toUpperCase() : ''
);
}}
/>
);
const App = () => (
<Formik
initialValues={{
email: '',
password: '',
select: '',
tags: [],
rememberMe: true,
}}
validate={values => {
const errors: Partial<Values> = {};
if (!values.email) {
errors.email = 'Required';
} else if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Invalid email address';
}
return errors;
}}
onSubmit={(values, {setSubmitting}) => {
setTimeout(() => {
setSubmitting(false);
alert(JSON.stringify(values, null, 2));
}, 500);
}}
render={({submitForm, isSubmitting, values, setFieldValue}) => (
<Form>
<Field
name="email"
type="email"
label="Email"
variant="outlined"
component={UppercasingTextField}
/>
<br />
<Field
type="password"
label="Password"
name="password"
component={TextField}
/>
<br />
<FormControlLabel
control={
<Field label="Remember Me" name="rememberMe" component={Switch} />
}
label="Remember Me"
/>
<br />
<Field
type="text"
name="select"
label="With Select"
select
variant="outlined"
helperText="Please select Range"
margin="normal"
component={TextField}
InputLabelProps={{
shrink: true,
}}
>
{ranges.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Field>
<br />
<FormControl>
<InputLabel shrink={true} htmlFor="tags">
Tags
</InputLabel>
<Field
type="text"
name="tags"
component={Select}
variant="outlined"
multiple={true}
inputProps={{name: 'tags', id: 'tags'}}
>
<MenuItem value="dogs">Dogs</MenuItem>
<MenuItem value="cats">Cats</MenuItem>
<MenuItem value="rats">Rats</MenuItem>
<MenuItem value="snakes">Snakes</MenuItem>
</Field>
</FormControl>
<br />
{isSubmitting && <LinearProgress />}
<br />
<Button
variant="contained"
color="primary"
disabled={isSubmitting}
onClick={submitForm}
>
Submit
</Button>
</Form>
)}
/>
);
render(<App />, document.getElementById('root'));
To show the With Select label as place holder at first time. While we select an option the with select label shows on top . In this code the label always shows at top.
the example here.Thanks in advance
just remove shrink={true}
<FormControl>
<InputLabel htmlFor="tags">
Tags
</InputLabel>
<Field
type="text"
name="tags"
component={Select}
variant="outlined"
multiple={true}
inputProps={{name: 'tags', id: 'tags'}}
>
<MenuItem value="dogs">Dogs</MenuItem>
<MenuItem value="cats">Cats</MenuItem>
<MenuItem value="rats">Rats</MenuItem>
<MenuItem value="snakes">Snakes</MenuItem>
</Field>
</FormControl>
Related
I have developed a short questionnaire in React using Material-UI as shown below. I am pulling the questions from a json file I have that looks like the following:
[ {
"id": 1,
"question": "Which section 1 criterion are applicable?"
"criterion": ["1.1", "1.2", "1.3"]
"decision": "Yes"
},
{
"id": 2,
"question": "Which section 2 criterion are applicable?"
"criterion": ["2.1", "2.2", "2.3"]
"decision": "No"
},
...
]
At the start of the questionnaire, all criteria are added to applicableCriteria (shown below). Based on the user's responses, I am trying to remove criterion from applicableCriteria. For example, if the user responds 'Yes' to question 1, the list of criterion shown for the question with id=1 should be removed from applicableCriteria. I have experimented with some different things, but my novice JavaScript skills haven't gotten me far. Below is a working, error-free version of what I've been working with. Any tips on how I should go about this successfully?
import * as React from "react";
import TextField from "#mui/material/TextField";
import {
Button,
Radio,
RadioGroup,
FormControlLabel,
FormControl,
FormLabel,
FormHelperText,
FormGroup,
Checkbox,
Grid,
Box,
} from "#mui/material";
import { useForm } from "react-hook-form";
import Records from "./CriterionQuestions.json";
const QuestionnaireForm = () => {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm();
const onSubmit = (data) => console.log(data);
console.log(errors);
let applicableCriteria = [];
// Push all possible criteria to list
for (let q = 0; q < Records.length; q++) {
for (let c = 0; c < Records[q].criterion.length; c++) {
applicableCriteria.push(Records[q].criterion[c]);
}
}
return (
<div className="App__form">
<h1> Questionnaire </h1>
<h2>{applicableCriteria}</h2>
<form onSubmit={handleSubmit(onSubmit)}>
{/* Radio button */}
<FormControl error={Boolean(errors.question1)}>
<FormLabel component="legend">
{/* {" "}
Is the modification applicable to only fixed-wing and non-commercial
derivative aircraft?{" "} */}
{Records[0].question}
</FormLabel>
<RadioGroup row aria-label="question1" name="question1">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question1", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question1", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question1?.message}
</FormHelperText>
</FormControl>
<FormControl error={Boolean(errors.question2)}>
<FormLabel component="legend">{Records[1].question}</FormLabel>
<RadioGroup row aria-label="question2" name="question2">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question2", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question2", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question2?.message}
</FormHelperText>
</FormControl>
<div className="clearfix"></div>
<FormControl error={Boolean(errors.question8)}>
<FormLabel component="legend">{Records[7].question}</FormLabel>
<RadioGroup row aria-label="question8" name="question8">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question8", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question8", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question8?.message}
</FormHelperText>
</FormControl>
<div className="clearfix"></div>
<FormControl error={Boolean(errors.question9)}>
<FormLabel component="legend">{Records[8].question}</FormLabel>
<RadioGroup row aria-label="question9" name="question9">
<FormControlLabel
value="yes"
control={
<Radio
{...register("question9", {
required: "Please select a response.",
})}
/>
}
label="Yes"
/>
<FormControlLabel
value="no"
control={
<Radio
{...register("question9", {
required: "Please select a response.",
})}
/>
}
label="No"
/>
</RadioGroup>
<FormHelperText style={{ color: "#d32f2f" }}>
{errors.question9?.message}
</FormHelperText>
</FormControl>
<div className="clearfix"></div>
<TextField
id="outlined-basic"
name="modName"
label="Modification Name"
variant="outlined"
fullWidth
{...register("modName", {
required: "Modification Name is required.",
})}
error={Boolean(errors.modName)}
helperText={errors.modName?.message}
/>
{/* Check box */}
<Box sx={{ paddingTop: 3 }} />
<div className="clearfix"></div>
<Button
variant="contained"
color="primary"
type="submit"
className="btns"
>
Submit Responses
</Button>
</form>
</div>
);
};
export default QuestionnaireForm;
Currently, when I select city dropdown, it triggers a re-validation of already filled input fields.Image description here
I'm using the County-State-City library to look up the states and cities in the State and City select fields.
form section using formik
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { Formik, Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';
import AdminLeftNavbar from '../../components/AdminLeftNavbar';
import UploadImageToS3 from '../../components/UploadImageS3/UploadImageToS3';
import { clearMessage, setMessage } from '../../redux/messageSlice';
import { Country, State, City } from 'country-state-city';
import {
StyledHeaderWrapper,
StyledMainContainer,
StyledMainWrapper,
StyledBreadCrumbs,
StyledSectionTitle,
StyledContentWrapper,
OperatorVisibilityWrapper,
FormWrapper,
FormGroup,
DetailsWrapper,
AmenitiesParkingTypeWrapper,
OtherInfoWrapper,
OtherInfoHeader,
AddressWrapper,
AddressLocationWrapper,
AddressLocationGrandWrapper,
OperatorButtonWrapper,
AddressHeader,
CoordinatesHeader,
AddressContentWrapper,
OtherInfoSubWrapper,
} from './style';
import { createLocations } from '../../redux/locationsSlice';
import Loading from '../../components/Loading/Loading';
import FormikControl from '../../components/FormikComponents/FormikControl';
const NewLocations = () => {
const { operatorId } = useParams();
const [successful, setSuccessful] = useState(false);
const [showProfile, setShowProfile] = useState(true);
const operators = useSelector((state) => state.operators.data);
const operator = operators.filter(
(operator) => operator.id === parseInt(operatorId)
);
const { loading } = useSelector((state) => state.locations);
const dispatch = useDispatch();
const navigate = useNavigate();
const DEFAULT_COUNTRY = 'US';
useEffect(() => {
dispatch(clearMessage());
}, [dispatch]);
const availableAmenitiesSelection = [
'Smart Car',
'Self Park',
'Staffed',
'Paved',
'Driveaway',
'Mobile Pass',
'Twenty Four',
];
const availableParkingType = ['Outdoor', 'Covered', 'Indoor', 'UnCovered'];
const accessTypeOptions = [
{ key: 'Mobile Pay', value: 'mobile pay' },
{ key: 'Location Name', value: 'location name' },
];
const validationTypeOptions = [
{ key: 'By Plate', value: 'By Plate' },
{ key: 'Location Name', value: 'location name' },
];
const cityOption = [{ key: 'Abbeville', value: 'abbeville' }];
const updateTimezones = Country.getCountryByCode(DEFAULT_COUNTRY).timezones;
const initialValues = {
name: '',
bio: '',
operatedBy: '',
description: '',
images: '',
timeZone: '',
amenities: [],
parkingType: [],
numberOfSpaces: '',
operatorStreet: '',
accessType: '',
validationType: '',
address: {
street: '',
country: 'United States',
state: '',
city: '',
zip: '',
latitude: '',
longitude: '',
entranceLatitude: '',
entranceLongitude: '',
},
};
const validationSchema = Yup.object().shape({
name: Yup.string().required('Required!'),
bio: Yup.string().required('Required!'),
description: Yup.string().required('Required!'),
operatedBy: Yup.string().required('Required!'),
// images: Yup.string().required('Required!'),
timeZone: Yup.string().required('Required!'),
amenities: Yup.array().required('Required!'),
parkingType: Yup.array().required('Required!'),
numberOfSpaces: Yup.number()
.required('Required!')
.min(0, 'Number must be positive integer'),
accessType: Yup.string().required('Required!'),
validationType: Yup.string().required('Required!'),
address: Yup.object().shape({
street: Yup.string().required('Required!'),
// state: Yup.string().required('Required!'),
// city: Yup.string().required('Required!'),
zip: Yup.string()
.required('Required')
.matches(/^[0-9]+$/, 'Must be only digits')
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits'),
latitude: Yup.number().required('Required!'),
longitude: Yup.number().required('Required!'),
entranceLatitude: Yup.number().required('Required!'),
entranceLongitude: Yup.number().required('Required!'),
}),
});
const handleLocations = (formValue) => {
const {
name,
bio,
operatedBy,
description,
timeZone,
numberOfSpaces,
images,
amenities,
parkingType,
accessType,
validationType,
address: {
street,
state,
city,
zip,
latitude,
longitude,
entranceLatitude,
entranceLongitude,
},
} = formValue;
setSuccessful(false);
dispatch(
createLocations({
operatorId,
name,
bio,
description,
operatedBy,
timeZone,
numberOfSpaces,
amenities,
parkingType,
accessType,
validationType,
images,
address: {
street,
state,
city,
zip,
latitude,
longitude,
entranceLatitude,
entranceLongitude,
},
})
)
.unwrap()
.then(() => {
setSuccessful(true);
dispatch(setMessage('Signed up successfully.'));
navigate(`/admin/operators/${operatorId}/locations`);
})
.catch(() => {
setSuccessful(false);
});
};
const updatedStates = () =>
State.getStatesOfCountry(DEFAULT_COUNTRY).map((state) => ({
label: state.name,
value: state.isoCode,
...state,
}));
const updatedCities = (countryCode, isoCode) =>
City.getCitiesOfState(countryCode, isoCode).map((city) => ({
label: city.name,
value: city.isoCode,
...city,
}));
if (loading) {
return <Loading />;
}
return (
<StyledMainContainer>
<AdminLeftNavbar />
<StyledMainWrapper>
<StyledHeaderWrapper>
<StyledSectionTitle>Location Profile</StyledSectionTitle>
<StyledBreadCrumbs>
<Link to="/admin/operators">Operator Listings</Link> /
<span>General Info </span>
/ {' '}
<Link to={`/admin/operators/${operatorId}/locations`}>
Operator Locations
</Link>
</StyledBreadCrumbs>
</StyledHeaderWrapper>
<OperatorVisibilityWrapper>
<p className="operator">
Operator: <span>{operator.map((val) => val.name)}</span>
</p>
<div className="form-check form-switch form-check-reverse">
<input
className="form-check-input"
type="checkbox"
id="flexSwitchCheckReverse"
onClick={() => setShowProfile(!showProfile)}
/>
<label className="form-check-label" for="flexSwitchCheckReverse">
Public Profile Visibility:{' '}
<strong>{showProfile ? 'ON' : 'Hide'}</strong>
</label>
</div>
</OperatorVisibilityWrapper>
<StyledContentWrapper>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleLocations}
>
{(
// we need to use setFieldValue from Formik
{ values, setFieldValue, setValues }
) => (
<Form>
{!successful && (
<FormWrapper>
{showProfile ? (
<>
<h5>Profile</h5>
<FormGroup>
<FormikControl
control="input"
type="string"
label="Location Name"
name="name"
className="form-control field-width"
placeholder="V Lots"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="input"
type="string"
label="Bio"
name="bio"
className="form-control field-width"
placeholder="EV Charging Stations, Reservation only, Crystal Mountain US"
autoComplete="off"
/>
</FormGroup>
</>
) : null}
<h5>Hero Image</h5>
<FormGroup>
<FormikControl
control="textarea"
type="text"
label=""
name="images"
className="form-control hero-field-width"
src=""
/>
<Field name="images">
{({ form }) => (
<UploadImageToS3 setFieldValue={form.setFieldValue} />
)}
</Field>
</FormGroup>
<DetailsWrapper>
<h5>Details</h5>
<FormGroup>
<FormikControl
control="input"
type="string"
label="Operated By"
name="operatedBy"
className="form-control field-width"
placeholder="Crystal parking(Mineapolis, St.paul)"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="textarea"
label="Description"
name="description"
className="form-control field-width"
placeholder="Type your Description"
autoComplete="off"
/>
</FormGroup>
<AmenitiesParkingTypeWrapper>
<FormGroup>
<label htmlFor="amenities">
Amenities:
<Field
component="select"
name="amenities"
// You need to set the new field value
onChange={(evt) =>
setFieldValue(
'amenities',
[].slice
.call(evt.target.selectedOptions)
.map((option) => option.value)
)
}
multiple={true}
>
{availableAmenitiesSelection.map((amenity) => (
<option key={amenity} value={amenity}>
{amenity}
</option>
))}
</Field>
<ErrorMessage
name="amenities"
component="div"
className="alert alert-danger"
/>
</label>
</FormGroup>
<FormGroup>
<label htmlFor="parkingType">
Parking Type:
<Field
component="select"
name="parkingType"
// You need to set the new field value
onChange={(evt) =>
setFieldValue(
'parkingType',
[].slice
.call(evt.target.selectedOptions)
.map((option) => option.value)
)
}
multiple={true}
>
{availableParkingType.map((parking) => (
<option key={parking} value={parking}>
{parking}
</option>
))}
</Field>
<ErrorMessage
name="parkingType"
component="div"
className="alert alert-danger"
/>
</label>
</FormGroup>
</AmenitiesParkingTypeWrapper>
</DetailsWrapper>
<OtherInfoHeader>
<h5>Other Info</h5>
</OtherInfoHeader>
<OtherInfoWrapper>
<OtherInfoSubWrapper>
<FormGroup>
<FormikControl
control="input"
type="number"
label="No. Of Spaces"
name="numberOfSpaces"
className="form-control field-width mb-2"
placeholder="20"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="select"
label="Access Type"
name="accessType"
options={accessTypeOptions}
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="select"
label="Validation Type"
name="validationType"
options={validationTypeOptions}
autoComplete="off"
/>
</FormGroup>
</OtherInfoSubWrapper>
<FormGroup>
<FormikControl
control="select"
label="Time Zone"
name="timeZone"
options={updateTimezones.map((timezone) => ({
value: timezone.zoneName,
key: timezone.zoneName,
}))}
placeholder="Eastern standard Time"
/>
</FormGroup>
</OtherInfoWrapper>
<AddressWrapper>
<AddressHeader>
<h5>Address</h5>
</AddressHeader>
<AddressContentWrapper>
<FormGroup>
<FormikControl
control="input"
type="string"
label="Street"
name="address.street"
className="form-control field-width mb-2"
placeholder="City Parking - 113 6th Ave..."
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="select"
label="State"
id="state"
name="address.state"
className="field-width"
options={updatedStates(
values.country ? values.country.value : null
).map((state) => ({
value: state.isoCode,
key: state.name,
}))}
value={values.state}
onChange={(e) => {
e.preventDefault();
setValues(
{ state: e.target.value, city: null },
false
);
}}
/>
</FormGroup>
<FormGroup>
<FormikControl
control="select"
label="City"
id="city"
name="address.city"
className="field-width"
options={
values.state
? updatedCities(
DEFAULT_COUNTRY,
values.state
).map((city) => ({
value: city.isoCode,
key: city.name,
}))
: cityOption
}
value={values.city}
onChange={(e) => {
e.preventDefault();
setFieldValue('city', e.target.value);
}}
/>
</FormGroup>
</AddressContentWrapper>
<FormGroup>
<FormikControl
control="input"
type="string"
label="Zip Code"
name="address.zip"
className="form-control field-width"
placeholder="45545"
autoComplete="off"
/>
</FormGroup>
</AddressWrapper>
<AddressLocationGrandWrapper>
<CoordinatesHeader>
<h5>Coordinates</h5>
</CoordinatesHeader>
<AddressLocationWrapper>
<FormGroup>
<FormikControl
control="input"
type="number"
label="Latitude"
name="address.latitude"
className="form-control field-address-location"
placeholder="4.3566"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="input"
type="number"
label="Longitude"
name="address.longitude"
className="form-control field-address-location"
placeholder="6.779705"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="input"
type="number"
label="Entrance Location Latitude"
name="address.entranceLatitude"
className="form-control field-address-location"
placeholder="6.779701"
autoComplete="off"
/>
</FormGroup>
<FormGroup>
<FormikControl
control="input"
type="number"
label="Entrance Location Longitude"
name="address.entranceLongitude"
className="form-control field-address-location"
placeholder="6.779701"
autoComplete="off"
/>
</FormGroup>
</AddressLocationWrapper>
</AddressLocationGrandWrapper>
<OperatorButtonWrapper>
<button
type="submit"
className="operator-cancel"
onClick={() =>
navigate(`/admin/operators/${operatorId}/locations`)
}
>
Cancel
</button>
<button type="submit">Save</button>
</OperatorButtonWrapper>
</FormWrapper>
)}
</Form>
)}
</Formik>
</StyledContentWrapper>
</StyledMainWrapper>
</StyledMainContainer>
);
};
export default NewLocations;
select function
import { ErrorMessage, Field } from 'formik';
import TextError from '../TextError/TextError';
const Select = (props) => {
const { label, name, options, ...rest } = props;
return (
<div>
<label htmlFor={name}>{label}</label>
<Field as="select" id={name} name={name} {...rest}>
{options.map((option) => {
return (
<option key={option.value} value={option.value}>
{option.key}
</option>
);
})}
</Field>
<ErrorMessage name={name} component={TextError} />
</div>
);
};
export default Select;
FormikControl component
import CheckboxGroup from './CheckboxGroup/CheckboxGroup';
import DatePicker from './DatePicker/DatePicker';
import Input from './InputForm/Input';
import RadioButtons from './RadioButtons/RadioButtons';
import Select from './SelectForm/Select';
import Textarea from './Textarea/Textarea';
const FormikControl = (props) => {
const { control, ...rest } = props;
switch (control) {
case 'input':
return <Input {...rest} />;
case 'textarea':
return <Textarea {...rest} />;
case 'select':
return <Select {...rest} />;
case 'radio':
return <RadioButtons {...rest} />;
case 'checkbox':
return <CheckboxGroup {...rest} />;
case 'date':
return <DatePicker {...rest} />;
default:
return null;
}
};
export default FormikControl;
Any idea on how I can prevent this uncontrolled event triggerring is humbly welcome.
im quite new on reactJS and also ant design. right now im trying to get a value from a Form.List that i want to make it / render it as json nested data output.
my full code :
import { MinusCircleOutlined, PlusOutlined } from '#ant-design/icons';
import { Button, Form, Input, Space, DatePicker, Select } from 'antd';
import axios from 'axios'
import { useNavigate } from 'react-router-dom'
import Cookies from "js-cookies";
import moment from 'moment';
import 'moment/locale/zh-cn';
const Stockpickingnew = ({ title }) => {
const options = [
{
value: '1',
label: 'True',
},
{
value: '0',
label: 'False',
},
{
value: '7',
label: 'product_tmpl_id'
},
];
const Navigate = useNavigate()
const dateFormat = ['DD-MM-YYYY'];
//---------------------------------------------------------------------------------------------------------------
let headers = {
"Authorization": "Bearer " + Cookies.getItem('access_token')
}
const onFinish = (values) => {
console.log('Success:', values);
let stockpick = {
date: moment(values.date).format("DD-MM-YYYY"),
origin: values.origin,
picking_type_id: values.picking_type_id,
location_id: values.location_id,
location_dest_id: values.location_dest_id,
stock_move_ids: [{
demand: values.demand,
done: values.done,
product_uom: values.product_uom,
product_tmpl_id: values.product_tmpl_id,
}]
};
console.log(JSON.stringify(stockpick))
let params = JSON.stringify(stockpick)
axios.post('http://127.0.0.1:5000/api/stockpickings', params, { headers })
.then(() => {
Navigate('/')
})
.catch(error => {
if (error.response) {
console.log(error.response);
}
});
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
//---------------------------------------------------------------------------------------------------------------
return (
<>
<div className='new'>
<div className="top">
<h1>{title}</h1>
</div>
<div className="bottom">
<div className="stockPicking">
<Form
name="stockPickings"
layout="vertical"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<div className="left">
<Form.Item
label="Origin :"
name='origin'
>
<Select
options={options}
placeholder="Origin"
/>
</Form.Item>
<Form.Item
label="Picking Type :"
name='picking_type_id'
>
<Select
options={options}
placeholder="Picking Type"
/>
</Form.Item>
<Form.Item
label="Date :"
name='date'
>
<DatePicker
format={dateFormat}
onChange={(dateInMomentFormat, dateInStringFormat) => {
console.log(dateInStringFormat);
}}
/>
</Form.Item>
</div>
<div className="right">
<Form.Item
label="Location :"
name='location_id'
>
<Select
options={options}
placeholder="Location"
/>
</Form.Item>
<Form.Item
label="Destination :"
name='location_dest_id'
>
<Select
options={options}
placeholder="Destination"
/>
</Form.Item>
</div>
<div className="stockMove">
<Form.Item>
<Form.List name="stock_move_ids">
{(fields, { add, remove }) => (
<>
{fields.map((field) => (
<Space
key={field.key}
style={{
display: 'flex',
marginBottom: 8,
}}
align="baseline"
>
<Form.Item
{...field}
name={[field.name, 'demand']}
key={[field.key, 'demand']}
rules={[
{
required: true,
message: 'Missing Demand',
},
]}
>
<Input placeholder="Demand" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'done']}
key={[field.key, 'done']}
>
<Select
options={options}
placeholder="Done"
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'product_uom']}
key={[field.key, 'product_uom']}
rules={[
{
required: true,
message: 'Missing product_uom',
},
]}
>
<Select
options={options}
placeholder="product_uom"
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'product_tmpl_id']}
key={[field.key, 'product_tmpl_id']}
rules={[
{
required: true,
message: 'Missing product_tmpl_id',
},
]}
>
<Select
options={options}
placeholder="product_tmpl_id"
/>
</Form.Item>
<MinusCircleOutlined onClick={() => remove(field.name)} />
</Space>
))}
<Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
Add field
</Button>
</Form.Item>
</>
)}
</Form.List>
</Form.Item>
</div>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
</>
)
}
export default Stockpickingnew
im sorry if it's really hard to read but basically, what i really want to do is my Form.List can get a value as nested data like :
stock_move_ids: [{
demand: values.demand,
done: values.done,
product_uom: values.product_uom,
product_tmpl_id: values.product_tmpl_id,
}]
my console.log (values) and console.log JSON.stringify(stockpick) do have different result as image below.
first one is from console.log values and the bottom one is from console.log stockpick
Screenshoot here
stock_move_ids values have 0th index you can access it like this.
let stockpick = {
date: moment(values.date).format("DD-MM-YYYY"),
origin: values.origin,
picking_type_id: values.picking_type_id,
location_id: values.location_id,
location_dest_id: values.location_dest_id,
stock_move_ids: [
{
demand: values?.stock_move_ids?.[0]?.demand,
done: values?.stock_move_ids?.[0]?.done,
product_uom: values?.stock_move_ids?.[0]?.product_uom,
product_tmpl_id: values?.stock_move_ids?.[0]?.product_tmpl_id,
},
],
};
In my flight booking application the admin enters destination names while adding new flights. The admin can write the full country/City names (i.e. Sydney, New York etc.) But I want to save them as 3 letter abbreviation such as (SYD, NYC etc.) in the database when admin clicks the submit button. I tried using the i18n-iso-countries package but I'm not quite sure of implementing this. Is there any simple approach to this?
This is my form component:
import React, { useState } from "react";
import {
TextField,
FormControl,
InputLabel,
MenuItem,
Select,
RadioGroup,
FormControlLabel,
Radio,
Button,
} from "#mui/material";
import Autocomplete from "#mui/material/Autocomplete";
import DatePicker from "#mui/lab/DatePicker";
import AdapterDateFns from "#mui/lab/AdapterDateFns";
import LocalizationProvider from "#mui/lab/LocalizationProvider";
import SendIcon from "#mui/icons-material/Send";
import "./Form.css";
const destinations = [
{ title: "Sydney" },
{ title: "Paris" },
{ title: "Thailand" },
{ title: "France" },
{ title: "Dhaka" },
{ title: "Bangkok" },
{ title: "Indonesia" },
];
export default function Form() {
const dt = new Date().toLocaleDateString();
console.log(dt);
const [formData, setFormData] = useState({
from: "",
to: "",
depart: dt,
return: dt,
noOfPassenger: 1,
tripType: "Round Trip",
});
const defaultProps = {
options: destinations,
getOptionLabel: (option) => option.title,
};
const handleSubmit = () => {
if (formData.tripType === "One Way")
setFormData({ ...formData, return: "None" });
console.log(formData);
};
return (
<div className="form_parent">
<div className="inner_form">
<div className="from">
<Autocomplete
{...defaultProps}
onChange={(event, value) =>
setFormData({ ...formData, from: value.title })
}
renderInput={(params) => (
<TextField {...params} label="From" variant="outlined" required />
)}
/>
</div>
<div className="to">
<Autocomplete
{...defaultProps}
onChange={(event, value) =>
setFormData({ ...formData, to: value.title })
}
renderInput={(params) => (
<TextField {...params} label="To" variant="outlined" required />
)}
/>
</div>
<div className="dates">
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="Departure Date"
value={formData.depart}
disablePast
onChange={(e) =>
setFormData({
...formData,
depart: e.toLocaleDateString(),
})
}
renderInput={(params) => <TextField {...params} required />}
/>
</LocalizationProvider>
</div>
<div className="dates">
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
label="Return Date"
value={formData.return}
disablePast
disabled={formData.tripType === "One Way" ? true : false}
onChange={(e) =>
setFormData({
...formData,
return: e.toLocaleDateString(),
})
}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
</div>
<div className="dates">
<FormControl className="passenger">
<InputLabel id="passengerNo">No. of Passenger</InputLabel>
<Select
variant="outlined"
labelId="passengerNo"
value={formData.noOfPassenger}
required
label="No. of Passenger"
onChange={(e) =>
setFormData({ ...formData, noOfPassenger: e.target.value })
}
>
<MenuItem value={1}>1</MenuItem>
<MenuItem value={2}>2</MenuItem>
<MenuItem value={3}>3</MenuItem>
<MenuItem value={4}>4</MenuItem>
</Select>
</FormControl>
</div>
<div className="radio_buttons">
<FormControl component="fieldset">
<RadioGroup
row
aria-label="trip"
name="row-radio-buttons-group"
value={formData.tripType}
onChange={(e) =>
setFormData({ ...formData, tripType: e.target.value })
}
>
<FormControlLabel
value="One Way"
control={<Radio />}
label="One Way"
/>
<FormControlLabel
value="Round Trip"
control={<Radio />}
label="Round Trip"
/>
</RadioGroup>
</FormControl>
</div>
<div className="submit">
<Button
className="submit_btn"
variant="contained"
color="error"
onClick={handleSubmit}
endIcon={<SendIcon />}
>
Submit
</Button>
</div>
</div>
</div>
);
}
Model
import mongoose from "mongoose";
const flightSchema = mongoose.Schema({
from: String,
to: String,
price: String,
flightType: String,
airline: String,
date: {
type: Date,
default: new Date().toLocaleDateString(),
},
});
const FlightData = mongoose.model("FlightData", flightSchema);
export default FlightData;
I have a strange thing happening where I can't really figure out what is creating those double input field lines in my code (see the picture). I have literally copied the code from the official website (React Final Form) and it doesn't seem to be happening there. Does it have something to do with the browser compatibility?
My code:
import React from 'react';
import { Form } from 'react-final-form';
import {
TextField,
Select,
} from 'mui-rff';
import {
Grid,
Button,
MenuItem,
} from '#material-ui/core';
import { createMuiTheme } from '#material-ui/core/styles';
import { ThemeProvider } from '#material-ui/styles';
const theme = createMuiTheme({
palette: {
primary: {
main: '#008080',
},
}
})
const onSubmit = async values => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
await sleep(300);
window.alert(JSON.stringify(values, 0, 2));
};
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
}
if (!values.lastName) {
errors.lastName = 'Required';
}
if (!values.email) {
errors.email = 'Required';
}
return errors;
};
const formFields = [
{
size: 6,
field: (
<TextField
label="First Name"
name="firstName"
margin="none"
required={true}
/>
),
},
{
size: 6,
field: (
<TextField
label="Last Name"
name="lastName"
margin="none"
required={true}
/>
),
},
{
size: 12,
field: (
<TextField
type="email"
label="Email"
name="email"
margin="none"
required={true}
/>
),
},
{
size: 12,
field: <TextField name="notes" multiline label="Notes" margin="none" />,
},
{
size: 12,
field: (
<Select
name="city"
label="Select a City"
formControlProps={{ margin: 'none' }}
>
<MenuItem value="London">London</MenuItem>
<MenuItem value="New York">New York</MenuItem>
<MenuItem value="Tallinn">Tallinn</MenuItem>
</Select>
)
}
];
const FinalForm = () => {
return (
<div className="col s12 m6">
<div className="card-panel grey lighten-3">
<h5>Please fill out this form</h5>
<Form
onSubmit={onSubmit}
validate={validate}
render={({ handleSubmit, form, submitting, pristine }) => (
<form onSubmit={handleSubmit} noValidate>
<Grid container alignItems="flex-start" spacing={2}>
{formFields.map((item, idx) => (
<Grid item xs={item.size} key={idx}>
{item.field}
</Grid>
))}
<Grid item style={{ marginTop: 16 }}>
<Button
type="button"
variant="contained"
onClick={form.reset}
disabled={submitting || pristine}
>
Reset
</Button>
</Grid>
<Grid item style={{ marginTop: 16 }}>
<ThemeProvider theme={theme}>
<Button
variant="contained"
type="submit"
color='primary'
disabled={submitting}
>
Submit
</Button>
</ThemeProvider>
</Grid>
</Grid>
</form>
)}
/>
</div>
</div>
)
};
export default FinalForm;