I'm using antd in react render a form with dynamic add and remove form.item.
In each form.item I'm trying to set an option which the day disable when it been selected in previous form.item.
So I was thinking about maybe I can use state that can set the day disable.
const [weekDays, setWeekDays] = useState({
Monday: false,
Tuesday: false,
Wednesday: false,
Thursday: false,
Friday: false,
Saturday: false,
Sunday: false,
});
And the form was like this
<Form.List name="classTime">
{(fields, { add, remove }) => (
<>
{fields.map((field) => (
<Row key={field.key} align="baseline">
<Col span={8}>
<Form.Item
noStyle
shouldUpdate={(prevValues, curValues) =>
prevValues.area !== curValues.area ||
prevValues.sights !== curValues.sights
}
>
{() => (
<Form.Item
{...field}
name={[field.name, "weekday"]}
fieldKey={[field.fieldKey, "weekday"]}
rules={[
{ required: true, message: "Missing weekday" },
]}
>
<Select
disabled={false}
style={{ width: 130 }}
onChange={(value) => {
setWeekDays(value.true);
}}
>
{Object.entries(weekDays).map(([item,value]) => (
<Option
key={item}
value={item}
disabled={value}
>
{item}
</Option>
))}
</Select>
</Form.Item>
)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
{...field}
name={[field.name, "time"]}
fieldKey={[field.fieldKey, "time"]}
// normalize={(value) => moment(value).format("HH:mm:ss")}
rules={[{ required: true, message: "Missing time" }]}
>
<TimePicker style={{ width: "100%" }} />
</Form.Item>
</Col>
<Col span={2}>
<MinusCircleOutlined onClick={() => remove(field.name)} />
</Col>
</Row>
))}
<Row>
<Col span={20}>
<Form.Item>
<Button
type="dashed"
onClick={() => add()}
block
icon={<PlusOutlined />}
>
Add Class Time
</Button>
</Form.Item>
</Col>
</Row>
</>
)}
</Form.List>
it seems good but when I select a day will error me
Unhandled Runtime Error
TypeError: Cannot convert undefined or null to object
can't figure out why.
Related
I have a form built with Formik containing an array of objects. When I add a second element to the form with the add-button, I get the following error:
Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
I have made sure that initial values is defined for the the form. I use the FieldArray component from formik. If I remove the time and rate fields, so it's only the name input in each object, I don't get the error, but when I add the time and rate fields, the error occurs. The component contains the following:
const TimeItemsForm = () => {
const jiraItemsStore = useJiraItemsStore();
function jiraTimeImported(timeItemIndex: number, importedHoursTotal: number, checkedItems: CheckedTimeItems) {
// Add checked items to store
jiraItemsStore.setJiraTable(timeItemIndex, checkedItems, importedHoursTotal);
}
const TimeItemSchema = Yup.object().shape({
name: Yup.string().required('Required'),
time: Yup.number().min(0).required('Required'),
// rate: Yup.number().min(0).required('Required'),
});
const TimeItemsSchema = Yup.object().shape({
timeItems: Yup.array().of(TimeItemSchema),
})
const initialValues = {
timeItems: [
{
name: '',
time: 0,
rate: 0,
},
],
};
return (
<>
<Formik
validateOnChange={false}
initialValues={initialValues}
validationSchema={TimeItemsSchema}
onSubmit={(values) => console.log(values)}>
{({ values, errors, touched }) => (
<Form onChange={() => console.log("hs")}>
<FieldArray
name="timeItems"
render={arrayHelpers => (
<div>
{values.timeItems && values.timeItems.length > 0 ? (
values.timeItems.map((timeItem, index) => (
<React.Fragment key={index}>
<Stack gap={2}>
<Flex alignItems="end" gap={4}>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].name">Name</FormLabel>
<Field as={Input} placeholder="Time Item Name" variant="filled" name={`timeItems[${index}].name`} />
</FormControl>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].time">Time</FormLabel>
<InputGroup>
<Field as={Input} type="number" placeholder="0 Hours" variant="filled" name={`timeItems[${index}].time`} />
<InputRightAddon children='Hours' />
</InputGroup>
</FormControl>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].rate">Rate</FormLabel>
<InputGroup>
<Field as={Input} type="number" placeholder="USD 0" variant="filled" name={`timeItems[${index}].rate`} />
<InputRightAddon children='Hours' />
</InputGroup>
</FormControl>
<Flex flexShrink="0" gap={3} direction="column">
<Heading fontWeight="normal" size="sm">Apply Taxes & Discounts</Heading>
<Flex mb={0.5} gap={4}>
<Tooltip label='Tax 1' fontSize='sm'>
<IconButton variant={true ? 'solid' : 'outline'} aria-label='Tax' icon={<TbReceipt />} />
</Tooltip>
<IconButton variant='outline' aria-label='Discount' icon={<TbDiscount />} onClick={() => arrayHelpers.insert(index, { name: "", email: "" })} />
</Flex>
</Flex>
</Flex>
<Flex py={2} gap={10} justifyContent="space-between">
<TimeItemsTable timeItemIndex={index} jiraTimeImported={jiraTimeImported} />
<Flex gap={4}>
<IconButton aria-label='Create Time Item' icon={<MinusIcon />} onClick={() => arrayHelpers.remove(index)} />
<IconButton aria-label='Create Time Item' icon={<AddIcon />} onClick={() => arrayHelpers.insert(index, { name: "", email: "" })} />
</Flex>
</Flex>
</Stack>
<Divider my={4} />
</React.Fragment>
))
) : (
<button type="button" onClick={() => arrayHelpers.push('')}>
Add a Time Item
</button>
)}
<Flex mt={6} gap={10} justifyContent="space-between">
<Button colorScheme="purple" type="submit">Save</Button>
{/* <TimeItemsStats /> */}
</Flex>
</div>
)}
/>
</Form>
)}
</Formik>
</>
)
}
Solution:
The arrayHelpers.push and arrayHelpers.insert didn't insert the values with the correct type, as seen in the code.
I need to validate like at list one field required date field either list tree dropdown so what my task is like if the user selects only one means if the user selects only list dropdown then user able to submit that if the user selects only date field then user able to submit it if the user does not select any one field user not able to submit it I added condition but not working properly need to set like one field needs to be selected and also not sure why I need this dependency ["list", "Start_Date"] if I am not adding this getting error Error: Cyclic dependency, a node was: "Start_Date".
const validationSchema = Yup.object().shape({
validation: Yup.object().shape(
{
list: Yup.array().when("Start_Date", {
is: "",
then: Yup.array()
.of(Yup.string())
.min(1, "Required!")
.required("Required!"),
otherwise: Yup.array(),
}),
Start_Date: Yup.string().when("list", {
is: (listItemId) => listItemId?.length === 0,
then: Yup.string().required("This field is required."),
otherwise: Yup.string(),
}),
},
[ "list", "Start_Date" ]
),
});
const DeltaForm = useFormik({
initialValues: {
list: [],
Start_Date: "",
End_Date: "",
},
validationSchema,
onSubmit: (values) => {
updateSanctionsFilter(values);
},
});
return (
<Card variant="outlined">
<form onSubmit={DeltaForm.handleSubmit}>
<CardContent>
<Box mb={2}>
<Box mb={1}>
<Typography color="primary" variant="subtitle1">
Delta Change
</Typography>
</Box>
<Divider></Divider>
</Box>
<Grid container display="flex" spacing={4}>
<Grid item xs={12} sm={6} md={6}>
<TextField
id="outlined-select-currency"
label="Start Date"
variant="outlined"
size="small"
type="date"
InputLabelProps={{
shrink: true,
}}
onChange={DeltaForm.handleChange}
value={DeltaForm.values.Start_Date}
error={Boolean(DeltaForm.errors.Start_Date)}
helperText={DeltaForm.errors.Start_Date}
name="Start_Date"
></TextField>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<TextField
id="outlined-select"
label="End Date"
variant="outlined"
size="small"
type="date"
InputLabelProps={{
shrink: true,
}}
onChange={DeltaForm.handleChange}
value={DeltaForm.values.End_Date}
error={Boolean(DeltaForm.errors.End_Date)}
helperText={DeltaForm.errors.End_Date}
name="End_Date"
></TextField>
</Grid>
</Grid>
<Box mt={2}>
<MultiSelectWithTree
label="Select Sanctions list"
onChange={(newVal) => {
DeltaForm.setFieldValue("list", newVal);
}}
value={DeltaForm.values.list ? DeltaForm.values.list : []}
name="list"
error={DeltaForm.errors.list}
helperText={DeltaForm.errors.list}
variant="outlined"
size="small"
treeData={treeData?.length ? treeData : []}
/>
</Box>
<Box mb={2}>
<FormHelperText
error={Boolean(
DeltaForm.errors.selected || DeltaForm.errors.isCheck
)}
>
{DeltaForm.errors.selected || DeltaForm.errors.isCheck}
</FormHelperText>
</Box>
<Divider></Divider>
<Grid xs={12} item>
<Box
mt={2}
display="flex"
alignItems="flex-end"
flexDirection="column"
>
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
</Box>
</Grid>
</CardContent>
</form>
</Card>
);
const AddPartQuestionModalAgain = ({
isModalVisible,
hideModal,
questionData = {
question_no: '',
question_parts: [''],
},
}) => {
const dispatch = useDispatch()
let formInput
console.log(questionData)
return (
<>
<Modal
visible={isModalVisible}
onCancel={() => {
formInput.resetFields()
hideModal()
}}
width={1200}
>
<Form
layout='vertical'
ref={(ref) => {
formInput = ref
}}
name='dynamic_form_item'
>
<Form.List name='question_parts' key='question_parts'>
{(fields, { add, remove }, { errors }) => (
<>
{fields.map((field, index) => (
<Space
key={field.key}
direction='vertical'
>
<Form.Item key={`QuestionPart${index}`}>
<Row>
<Col span={10}>
<div
style={{
overflow: 'auto',
height: 400,
width: 590,
}}
>
<Form.Item
{...field}
label={`Question Part ${index + 1} Description`}
fieldKey={[field.fieldKey, 'part_desc']}
name={[field.name, 'part_desc']}
key={`part_desc${index}`
>
<Input.TextArea
rows={8}
placeholder='Description'
/>
</Form.Item>
<Form.Item
{...field}
label={`Question Part ${index + 1} Marks`}
fieldKey={[field.fieldKey, 'part_total_marks']}
name={[field.name, 'part_total_marks']}
key={`part_total_marks${index}`}
>
<Input
placeholder='Marks'
style={{
border: '1px solid black',
width: 450,
}}
/>
</Form.Item>
</div>
</Col>
<div class='vl'></div>
<Col span={12} offset={2}>
<div
>
<Form.List
{...field}
name='part_guided_answer'
fieldKey={[field.fieldKey, 'part_guided_answer']}
name={[field.name, 'part_guided_answer']}
key={`part_guided_answer${index}`}
>
{(fields, { add, remove }, { errors }) => (
<>
{fields.map((field, index) => (
<Space
key={field.key}
direction='vertical'
>
<Form.Item key={`QuestionPart${index}`}>
<Form.Item
{...field}
label={` Question Part Guided Answer ${
index + 1
}`}
fieldKey={[
field.fieldKey,
'part_model_ans',
]}
name={[field.name, 'part_model_ans']}
key={`part_model_ans${index}`}
>
<Input.TextArea
rows={4}
placeholder='Guided Answer'
/>
</Form.Item>
<Form.Item
{...field}
label={`Question Part
Guided Answer Marks ${index + 1}`}
fieldKey={[
field.fieldKey,
'part_answer_mark',
]}
name={[
field.name,
'part_answer_mark',
]}
key={`part_answer_mark${index}`}
>
<Input
placeholder='Guided Answer Marks'
}}
/>
</Form.Item>
<MinusCircleOutlined
className='dynamic-delete-button'
onClick={() => remove(field.name)}
/>
</Form.Item>
</Space>
))}
<Form.Item style={{ fontWeight: 'bold' }}>
<Button
type='dashed'
onClick={() => add()}
icon={<PlusOutlined />}
>
Add Question Part Guided Answer
</Button>
<Form.ErrorList errors={errors} />
</Form.Item>
</>
)}
</Form.List>
</div>
</Col>
<MinusCircleOutlined
className='dynamic-delete-button'
onClick={() => remove(field.name)}
/>
</Row>
<div class='vr'></div>
</Form.Item>
</Space>
))}
<Form.Item>
<Button
type='dashed'
onClick={() => add()}
icon={<PlusOutlined /
>
Add Question Part
</Button>
<Form.ErrorList errors={errors} />
</Form.Item>
</>
)}
</Form.List>
</Form>
</Modal>
</>
)
}
The above code basically gives me this picture below
what I would like to do is hide the items that already exist which is in the blue circle and only show items without anything inside and I would also like to have it so that it resets every time I open it because right now(see picture below) even if there is nothing inside it shows me this
that's because in my database my table for these values are null
| Question_id |part_id | part_desc | part_model_ans|answer_mark|
| ------------|--------------|-----------| --------------|-----------|
|10 | null | null | null |null |
|10 | null |null | null |null |
you can hide it like this, Since you can count the string of the text, In your case the text will be coming from server right
return (<div>
{firstname.length > 0 ? null: <p>FirstName</p> }
{secondName.length > 0 ? null: <p>secondName</p> }
{thirdName.length > 0 ? null: <p>thirdName</p> }
</div>)
So i put together this Dynamic Form Below (Hotel Rooms) and inside it you can also create dynamic forms (Room Beds). It works, i can add rooms & Beds and the object array is returned in the console.log (onSubmit).
codesandbox: https://codesandbox.io/s/charming-hermann-nzpbu?file=/src/App.js
Issue:
If you add room1 and room2 and then delete room1, the array stays of length 2 and now it has "beds undefined" and it keeps growing when you add beds to other rooms! Help me solve this:
Object returned when you press next (in console). As you can see the array is not subtracting but it is also leaving the beds undefined when i delete a room:
listingDescription: "ss"
listingName: "aa"
pricePerMonth: 1
rooms: Array(2)
0: {roomname: "room2", beds: Array(1)}
1: {beds: undefined}
The Main Form:
import React from 'react';
import { useStateMachine } from 'little-state-machine';
import { useForm } from 'react-hook-form';
import { Row, Col, Input, InputNumber, Button, Form, Space } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '#ant-design/icons';
import FormControl from 'components/UI/FormControl/FormControl';
import AddListingAction from './AddListingAction';
import { FormHeader, Title, FormContent, FormAction } from './AddListing.style';
import BedForm from "./BedForm";
const BasicInformation = ({ setStep }) => {
const { action, state } = useStateMachine(AddListingAction);
const { control, register, errors, setValue, handleSubmit } = useForm();
const onSubmit = (data) => {
console.log(data);
};
return (
<Form onFinish={(e) => onSubmit(e)}>
<FormContent>
<FormHeader>
<Title>Step 1: Start with the basics</Title>
</FormHeader>
<Row gutter={30}>
<Col sm={12}>
<FormControl
label='Listing Name'
htmlFor='listingName'
error={errors.listingName && <span>This field is required!</span>}
>
<Form.Item
id='listingName'
name='listingName'
defaultValue={state.data.listingName}
control={control}
placeholder='Write a name for your listing here'
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
</FormControl>
</Col>
<Col sm={12}>
<FormControl
label='Price Per Night (USD)'
htmlFor='pricePerMonth'
>
<Form.Item
name='pricePerMonth'
id='pricePerMonth'
defaultValue={state.data.pricePerMonth}
control={control}
placeholder='00.00'
rules={[
{
required: true,
pattern: /^[0-9]*$/,
},
]}
>
<InputNumber min={0} />
</Form.Item>
</FormControl>
</Col>
</Row>
<FormControl
label='Listing Description'
htmlFor='listingDescription'
error={
errors.listingDescription && <span>This field is required!</span>
}
>
<Form.Item
id='listingDescription'
name='listingDescription'
defaultValue={state.data.listingDescription}
control={control}
placeholder='Tell people about your listing, rooms, location & amenities'
rules={[
{
required: true,
},
]}
>
<Input.TextArea rows={5} />
</Form.Item>
</FormControl>
<FormControl
label='How many rooms does your listing have?'
error={errors.guest && <span>This field is required!</span>}
>
{/* This is the Dynamic room Adder */}
<Form.List name='rooms'>
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field) => (
<Space
key={field.key}
style={{ display: 'flex', marginBottom: 8 }}
align='start'
>
<Form.Item
{...field}
name={[field.name, 'roomname']}
fieldKey={[field.fieldKey, 'roomname']}
rules={[
{ required: true, message: 'Missing room name' },
]}
>
<Input placeholder='Room Name' />
</Form.Item>
{/* This is the Dynamic bed Adder */}
<Form.Item>
<BedForm fieldKey={field.key} />
</Form.Item>
<MinusCircleOutlined
onClick={() => {
remove(field.name);
console.log(field)
}}
/>
</Space>
))}
<Button
type='dashed'
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add room
</Button>
</div>
);
}}
</Form.List>
</FormControl>
</FormContent>
<FormAction>
<div className='inner-wrapper'>
<Button type='primary' htmlType='submit'>
Next
</Button>
</div>
</FormAction>
</Form>
);
};
export default BasicInformation;
The Child Form (BedForm)
import React from 'react';
import { Form, Input, Button, Space, Select } from 'antd';
import { PlusOutlined, MinusCircleOutlined } from '#ant-design/icons';
const { Option } = Select;
//#ATT:this was created to make nested dynamic elements! This is hard!
const BedForm = (props) => {
return (
<>
<Form.List name={[props.fieldKey, 'beds']}>
{(beds, { add, remove }) => {
return (
<div>
{beds.map((bed, index2) => (
<Space
key={bed.key}
style={{ display: 'flex', marginBottom: 8 }}
align='start'
>
<Form.Item
// name={"aar"}
{...bed}
name={[bed.name, 'bed']}
fieldKey={[bed.fieldKey, 'bed']}
key={index2}
// noStyle
rules={[
{
required: true, message: 'Beds Missing'
},
]}
>
<Select placeholder="Please select a Bed Type">
<Option value='double'>Double(2 person)</Option>
<Option value='single'>Single (1 person)</Option>
<Option value='king'>King Size (2 person)</Option>
<Option value='queen'>Queen Size (2 person)</Option>
<Option value='Bunk'>Bunk Bed (1 person)</Option>
<Option value='sofa'>Sofa Bed (1 person)</Option>
</Select>
</Form.Item>
{/* <MinusCircleOutlined
onClick={() => {
remove(bed.name);
}}
/> */}
</Space>
))}
<Form.Item>
<Button
type='dashed'
onClick={() => {
add();
}}
>
<PlusOutlined /> Add Bed
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</>
);
};
export default BedForm;
Pass field.name instead of field.key or fieldKey on App.js
https://codesandbox.io/s/trusting-wind-elsdz?file=/src/App.js
I used the React ant design drawer , When the user did not complete the form, I clicked on the outer side of the drawer and tried to display the notification message. but its not working, anyone know how to do that correctly
stack blitz here
Code here
import React, { Component } from 'react';
import { render } from 'react-dom';
import 'antd/dist/antd.css';
import './style.css';
import { Drawer, Form, Button, Col, Row, Input, Select, DatePicker, Icon } from 'antd';
const { Option } = Select;
class App extends Component {
state = { visible: false };
showDrawer = () => {
this.setState({
visible: true,
});
};
onClose = () => {
this.setState({
visible: false,
});
};
render() {
return (
<div>
<Button type="primary" onClick={this.showDrawer}>
<Icon type="plus" /> New account
</Button>
<Drawer
title="Create a new account"
width={720}
onClose={this.onClose}
visible={this.state.visible}
bodyStyle={{ paddingBottom: 80 }}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="Name">
<Input placeholder="Please enter user name" />)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Url">
<Input
style={{ width: '100%' }}
addonBefore="http://"
addonAfter=".com"
placeholder="Please enter url"
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="Owner">
<Select placeholder="Please select an owner">
<Option value="xiao">Xiaoxiao Fu</Option>
<Option value="mao">Maomao Zhou</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Type">
<Select placeholder="Please choose the type">
<Option value="private">Private</Option>
<Option value="public">Public</Option>
</Select>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="Approver">
<Select placeholder="Please choose the approver">
<Option value="jack">Jack Ma</Option>
<Option value="tom">Tom Liu</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="DateTime">
<DatePicker.RangePicker
style={{ width: '100%' }}
getPopupContainer={trigger => trigger.parentNode}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={24}>
<Form.Item label="Description">
<Input.TextArea rows={4} placeholder="please enter url description" />)}
</Form.Item>
</Col>
</Row>
<div
style={{
position: 'absolute',
right: 0,
bottom: 0,
width: '100%',
borderTop: '1px solid #e9e9e9',
padding: '10px 16px',
background: '#fff',
textAlign: 'right',
}}
>
<Button onClick={this.onClose} style={{ marginRight: 8 }}>
Cancel
</Button>
<Button onClick={this.onClose} type="primary">
Submit
</Button>
</div>
</Drawer>
</div>
);
}
}
render(<App />, document.getElementById('root'));
You need to add the logic about displaying notification on the onClose method of the <Drawer/>. Note that this method takes as input the elements that can trigger 'close' of drawer which are a div (background mask), an svg (X icon) and a button (Cancel).
At the following example the error notification is displayed if any input is empty when the drawer mask is clicked.
You can find also the example here: https://stackblitz.com/edit/react-28u4zw
import React, { Component } from "react";
import { render } from "react-dom";
import "antd/dist/antd.css";
import "./style.css";
import {
message,
Drawer,
Form,
Button,
Col,
Row,
Input,
Select,
DatePicker,
Icon
} from "antd";
const { Option } = Select;
const FIELD_NAMES = ["name", "url", "owner", "type", "approver", "dates"];
const initialValues = FIELD_NAMES.reduce(
(fieldList, fieldName) => ({ ...fieldList, [fieldName]: null }),
{}
);
class App extends Component {
state = {
visible: false,
...initialValues
};
showDrawer = () => {
this.setState({
visible: true
});
};
onClose = e => {
this.setState({
visible: false
});
const emptyFieldNames = FIELD_NAMES.filter(
fieldName => !this.state[fieldName]
);
if (emptyFieldNames.length > 0 && e.target.tagName === "DIV") {
return message.error(
`Please fill ${emptyFieldNames.join(", ")} field(s)`
);
}
};
setInput = fieldName => e => {
this.setState({ [fieldName]: e.target.value });
};
setSelect = fieldName => val => {
this.setState({ [fieldName]: val });
};
setDate = fieldName => dateList => {
this.setState({ [fieldName]: dateList.length > 0 ? dateList : null });
};
render() {
return (
<div>
<Button type="primary" onClick={this.showDrawer}>
<Icon type="plus" /> New account
</Button>
<Drawer
title="Create a new account"
width={720}
onClose={this.onClose}
visible={this.state.visible}
bodyStyle={{ paddingBottom: 80 }}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="Name">
<Input
placeholder="Please enter user name"
onChange={this.setInput("name")}
/>
)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Url">
<Input
style={{ width: "100%" }}
addonBefore="http://"
addonAfter=".com"
placeholder="Please enter url"
onChange={this.setInput("url")}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="Owner">
<Select
placeholder="Please select an owner"
onChange={this.setSelect("owner")}
>
<Option value="xiao">Xiaoxiao Fu</Option>
<Option value="mao">Maomao Zhou</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Type">
<Select
placeholder="Please choose the type"
onChange={this.setSelect("type")}
>
<Option value="private">Private</Option>
<Option value="public">Public</Option>
</Select>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item label="Approver">
<Select
placeholder="Please choose the approver"
onChange={this.setSelect("approver")}
>
<Option value="jack">Jack Ma</Option>
<Option value="tom">Tom Liu</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="DateTime">
<DatePicker.RangePicker
style={{ width: "100%" }}
getPopupContainer={trigger => trigger.parentNode}
onChange={this.setDate("dates")}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={24}>
<Form.Item label="Description">
<Input.TextArea
rows={4}
placeholder="please enter url description"
/>
)}
</Form.Item>
</Col>
</Row>
<div
style={{
position: "absolute",
right: 0,
bottom: 0,
width: "100%",
borderTop: "1px solid #e9e9e9",
padding: "10px 16px",
background: "#fff",
textAlign: "right"
}}
>
<Button onClick={this.onClose} style={{ marginRight: 8 }}>
Cancel
</Button>
<Button onClick={this.onClose} type="primary">
Submit
</Button>
</div>
</Drawer>
</div>
);
}
}
render(<App />, document.getElementById("root"));