How can I customised the form of Ant Design? - javascript

I am trying to make inline form design using ant design but I am not able to make it customised version.
I have attached the code, image of output from the code and what I want form should look like.
Here is the code:
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
const layoutInline ={
labelCol: {
sm: {
offset: 0,
span: 20,
},
},
wrapperCol: {
sm: {
offset: 30,
span: 30,
},
},
}
return (
<div style={{width: "70%", padding: "4%"}}>
<div>
<Form
{...layoutInline}
form={form}
layout="inline"
>
<Form.Item label="Full Name" tooltip="This is a required field">
<Input placeholder="Full Name" />
</Form.Item>
<Form.Item
label="Age"
tooltip={{
title: 'Tooltip with customize icon',
icon: <InfoCircleOutlined />,
}}
onChange={updateAge}
value={age}
>
<Input placeholder="input placeholder" />
</Form.Item>
<Form.Item name="gender" label="Gender" rules={[{ required: true }]}>
<Select
placeholder="Select an option"
onChange={updateGender}
allowClear
>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>
{/* <Form.Item label="Full Name" tooltip="This is a required field">
<p>{gender} {age} {ethnicity} {AST} {platelets} {ASTupper} {ALT} {HBVDNA} {report}</p>
</Form.Item> */}
<Form.Item name="Ethnicity" label="Ethnicity" rules={[{ required: true }]}>
<Select
placeholder="Select an option"
onChange={updateEthnicity}
allowClear
>
<Option value="South-East-Asian">South East Asian</Option>
<Option value="South-Asian">South-Asian</Option>
<Option value="African">African</Option>
<Option value="Other">Other</Option>
</Select>
</Form.Item>
</Form>
</div>
It is coming out on the page like this.
What I want is that should look like this.
Can anyone guide me, how to achieve it?

1 - The value of offset and span follow the rulesĀ of Antd Grid Layout system and it cannot be more than 24 (24 columns).
2 - AddinglabelCol and wrapperCol on the Form element will apply the same layout for Every fields. As you'r desired deisgn, each fields has a different layout, so you'll need to apply it on each
3 - layout="inline" on Form means that they will just be all inline
Finally, the layout system on Antd Form is good to have vertically aligned fields. If you want to have a full control of the field display, you have to wrap each field your self and use custom style or Antd Grid columns.
You may need something like this :
https://codesandbox.io/s/form-methods-antd4123-forked-xo3zp?file=/index.js:922-2483
<Form form={form}>
<Row>
{* sm is only a breakpoint, you may need to add some more for better responsive *}
<Col sm={14}>
<Form.Item label="Full Name" tooltip="This is a required field">
<Input placeholder="Full Name" />
</Form.Item>
</Col>
<Col sm={{ offset: 2, span: 8 }}>
<Form.Item label="Age">
<Input placeholder="input placeholder" />
</Form.Item>
</Col>
</Row>
<Row>
<Col sm={8}>
<Form.Item
name="gender"
label="Gender"
rules={[{ required: true }]}
>
<Select placeholder="Select an option" allowClear>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>
</Col>
<Col sm={{ offset: 2, span: 8 }}>
<Form.Item
name="Ethnicity"
label="Ethnicity"
rules={[{ required: true }]}
>
<Select placeholder="Select an option" allowClear>
<Option value="South-East-Asian">South East Asian</Option>
<Option value="South-Asian">South-Asian</Option>
<Option value="African">African</Option>
<Option value="Other">Other</Option>
</Select>
</Form.Item>
</Col>
</Row>
</Form>

In my opinion try to avoid in-line style, add className to every component (even from Ant.) then in the CSS play with position (looks like you want flex and margin/padding)

Related

Cannot save data from Ant Design <Input.Group>

I tried making two input fields one for dimensions and one for weight, and both had seperate select drop down to allow the user to select a unit. I saw on Ant design docs that they had something similar, so I tried using that.
This is how I wanted it to be like:
Now i have filled my form with many other fields and they work just fine, on clicking the save button, I am not getting any data entered in the fields for dimensions or weight, nor their units. I have a standard save function which is called on 'onFinish' event:
const handleSubmit = (data) => {
console.log('data', data);
submit(data);
};
This is my code to generate the fields.
<Form onFinish={handleSubmit} >
<Row style={{ justifyContent: 'left' }}>
{<Col span={8}>
<div className="p-2 lbh-input">
<Form.Item
name="dimensions"
key="dimensions"
label="Dimensions (l x b x h)">
<Input.Group>
<Input
key='length'
name='length'
style={{ width: '15%' }}
type="number"
/>
<Input
key='breadth'
name='breadth'
style={{ width: '24%' }}
addonBefore="x"
type="number"
/>
<Input
key='height'
name='height'
style={{ width: '25%' }}
addonBefore="x"
type="number"
/>
<Select name='dimension_unit' key='dimension_unit' defaultValue="cm">
<Option value="mm">mm</Option>
<Option value="cm">cm</Option>
<Option value="inch">inch</Option>
<Option value="feet">feet</Option>
<Option value="m">m</Option>
</Select>
</Input.Group>
</Form.Item>
</div>
</Col>
}
{
<div className="p-2">
<Form.Item
key="weight"
name="weight"
label="Weight">
<Input.Group>
<Input
style={{ width: '50%' }}
type="number"
key="weight"
name="weight"
label="Weight"
className='noborderradius'
/>
<Select defaultValue="kg" name="weight_unit" key="weight_unit">
<Option value="kg">kg</Option>
<Option value="tonne">tonne</Option>
<Option value="g">g</Option>
</Select>
</Input.Group>
</Form.Item>
</div>}
</Row>
<button>SUBMIT</button>
</Form>
As you can see, i have tried using everythihg I can like label,name,key but no matter what happens, I get no data being sent no matter what I type in these two fields. What am i missing? Am i doing something wrong with <Form.item> ?
My ant design version is
"antd": "^4.3.4",
Input.Group is just for layout purposes, it does not group all your inputs into a single Form.Item. You still need to wrap all your inputs with Form.Item and attach the names there. Use the noStyle property to not override the Input.Group styling.
Also, defaultValue will give you this warning:
Warning: [antd: Form.Item] defaultValue will not work on controlled Field. You should use initialValues of Form instead.
So you can just do as it says, I've removed the styling for brevity
<Form
onFinish={handleSubmit}
initialValues={{ dimension_unit: 'cm', weight_unit: 'kg' }}
>
<Form.Item label="Dimensions (l x b x h)">
<Input.Group>
<Form.Item name="length" noStyle>
<Input type="number" />
</Form.Item>
<Form.Item name="breadth" noStyle>
<Input type="number" addonBefore="x" />
</Form.Item>
<Form.Item name="height" noStyle>
<Input type="number" addonBefore="x" />
</Form.Item>
<Form.Item name="dimension_unit" noStyle>
<Select>
<Option value="mm">mm</Option>
<Option value="cm">cm</Option>
<Option value="inch">inch</Option>
<Option value="feet">feet</Option>
<Option value="m">m</Option>
</Select>
</Form.Item>
</Input.Group>
</Form.Item>
<Form.Item label="Weight">
<Input.Group>
<Form.Item name="weight" noStyle>
<Input type="number" />
</Form.Item>
<Form.Item name="weight_unit" noStyle>
<Select>
<Option value="kg">kg</Option>
<Option value="tonne">tonne</Option>
<Option value="g">g</Option>
</Select>
</Form.Item>
</Input.Group>
</Form.Item>
<button>SUBMIT</button>
</Form>
Note that you don't need the key property.
demo: https://stackblitz.com/edit/react-41wakw?file=demo.tsx
What you can do is instead of wrapping the entire <Input.Group> with a single <Form.Item> you need to wrap each <Input> with its own <Form.Item> and give each one a unique key and name.
Working Code Sandbox
<Input.Group>
<Form.Item
name="length"
key="length"
>
<Input
style={{ width: '15%' }}
type="number"
/>
</Form.Item>
<Form.Item
key='breadth'
name='breadth'
>
<Input
style={{ width: '24%' }}
addonBefore="x"
type="number"
/>
</Form.Item>
...
</Input.Group>

Validate select list with react-hook-form

I want to implement validation for React form using react-hook-form. For input value I implemented this:
<div className='input-group mb-3'>
<Controller
control={control}
name={"email"} // the key of json
defaultValue={""}
render={({ field }) => (
<input
{...field}
type="email"
className="form-control"
placeholder="Email"
aria-label="email"
onChange={(e) => field.onChange(e.target.value)}
/>
)}
/>
</div>
For me it's not clear how I need to implement it for select menu:
<div className='input-group mb-3'>
<select
className='form-control form-select'
name='budget'
id='budget'
required=''
data-msg='Please select your budget.'
>
<option value=''>Budget</option>
<option value='budget3'>More than $500,000</option>
</select>
</div>
Wat is the proper way to implement it?
somethings like this works?
<Controller
control={control}
name="budget"
rules={{
budget: {
required: "Required",
},
}}
render={({ field }) => (
<select name="budget" onChange={field.onChange} value={field.value}>
<option value="">Please select your budget</option>
<option value="budget3">More than $500,000</option>
<option value="budget2">$250,000 - $500,000</option>
<option value="budget1">$100,000 - $250,000</option>
{/* more budgets */}
</select>
)}
/>;
control is destructured from useForm like so:
const { controls, register, setValue, ...moreEls } = useForm();

Elements are not rendered inside scrollable view

I am building an application using React and Electron-JS.
I am using form to display some information. To this form style is applied asstyle={{ overflow: 'scroll', height: '45vh' }}. When Form items overflows, scrollbar is added to it. But the problem is when I scroll down, the items were hidden till then will not be rendered fully. But when the screen is resized, they become visible again. This happens like once in 10 times.
I cannot reproduce it always.
I think React is not rendering the items which are not visible on the visible screen to gain performance.
Following is the code for the form component:
const style = { margin: '5px', height: '3.3vh', labelAlign: 'left' };
const inputStyle = { padding: '3px', height: '26px' };
export const ObjectPane = React.memo(({ objDetails }) => (
<Form
fields={Object.keys(objDetails).map(key => {
let value = null;
if (objDetails[key] === undefined) value = 'NA';
else if (objDetails[key] === null) value = 'No Value';
else value = objDetails[key];
return {
name: [`${key}`],
value
};
})}
style={{ overflow: 'scroll', height: '45vh' }}
onScroll={() => {}}
>
<Form.Item label="Object" name="obj" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Object Id" name="objId" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Distance Long. [m] " name="longitude" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Distance Lat. [m] " name="lateral" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Velocity Long. [m/s]" name="vel_long" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Velocity Lat. [m/s]" name="vel_lat" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="2 Wheeler Confidence" name="conf_twowheel" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="4 Wheeler Confidence" name="conf_fourwheel" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item
label="Pedestrian Confidence"
name="conf_pedestrian"
style={style}
>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item
label="Stationary Confidence"
name="conf_stationary"
style={style}
>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Object Type" name="obj_type" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="Type Confidence" name="conf_obj" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="long_cu_aeb" name="long_cu_aeb" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="cross_vru_aeb" name="cross_vru_aeb" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="long_cu_fcw" name="long_cu_fcw" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="cross_vru_fcw" name="cross_vru_fcw" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
<Form.Item label="cyc_ped_tipl" name="cyc_ped_tipl" style={style}>
<Input style={inputStyle} disabled />
</Form.Item>
</Form>
));
How can I make this work as expected? Please let me know if any more information needs to be added here.

Why the autofocus isn't working in ReactJS with antd?

I'm having trouble with the autoFocus, I searched a lot, but none solutions that I found worked for me, I'm using a Drawer with a form inside, that form has some Form.Item with Input, and when I open the drawer, I want to focus on form.item, anybody can help me?
Here is my code:
<Drawer>
<Form layout="vertical" ref={this.formRef} onFinish={this.onFinish} onFinishFailed={this.onFinishFailed}>
<Row gutter={16}>
<Col span={24}>
<Form.Item
name="description"
label="Description"
rules={[
{
required: true,
message: 'Please enter a description.',
},
]}
>
<Input.TextArea autoFocus rows={10} placeholder="Please enter a description." />
</Form.Item>
</Col>
</Row>
<Row style={{ bottom: '0', position: 'absolute', right: '38px' }}>
<Form.Item>
<Button
onClick={this.onClose}
style={{ marginRight: 8 }}
>
Cancel
</Button>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Row>
</Form>
</Drawer>
According to the docs, autoFocus is not supported prop (like it is on <input /> element). Haven't used this ui lib before, so can't say if setting focus manually by using ref would work.
UPDATE:
Just have played a bit and it looks like that focus can be set manually:
demo
code
Another update:
demo with drawer
code
const inputTagRef = useRef(null);
useEffect(() => {
if (inputTagRef.current) {
inputTagRef.current.focus();
}
}, [inputTagRef.current]);
<Input
ref={inputTagRef}
/>
This will add autoFocus to you input field using antd ui lib.

Change form.item label font size in AntD

I'm using styled components something like this
const FormItem = styled(Form.Item)`
font-size: 16px;
`;
Using Form Item something like this
<FormItem label="System Pressurized">
{getFieldDecorator('systemPressurized')(
<Select defaultValue="" placeholder="Select Type">
<Option value="Yiminghe">yiminghe</Option>
</Select>,
)}
</FormItem>
I've tried changing font size of AntD but it doesn't seem to workout
There are multiple options to override style elements.
You can directly override label elements from global CSS files like:
label {
font-size:16px;
}
Individual element by adding a script to the label element:
<FormItem
label={ <p style={{fontSize:"16px"}}>"System Pressurized"</p> }>
{ getFieldDecorator('systemPressurized')(
<Select defaultValue="" placeholder="Select Type">
<Option value="Yiminghe">yiminghe</Option>
</Select>
)}
</FormItem>
Please override CSS in your code like
$ .ant-form-item-label>label {
font-size: 16px;
}
You can directly override the CSS in global.less file like
& .ant-form-item-label {
& > label {
font-size: 16px;
}
}
You can write JSX for this
<FormItem label = {
<p style={{fontSize: "16px"}}>System Pressurized</p>}>
{getFieldDecorator('systemPressurized')(
<Select defaultValue="" placeholder="Select Type">
<Option value="Yiminghe">yiminghe</Option>
</Select>,
)}
you have two way to style the formItem label
//way one :
//You can override the default css by override below selectors
.form-section .form-group label{
font-size : 20px
//YOUR CUSTOM STYLE
}
// way two :
// You can pass custom component like below :
<FormItem label={<p style={YOURCUSTOMSTYLEOBJECT}>System Pressurized</p>}>
{getFieldDecorator('systemPressurized')(
<Select defaultValue="" placeholder="Select Type">
<Option value="Yiminghe">yiminghe</Option>
</Select>,
)}
</FormItem>
add css:
.ant-form-item-label label{
font-size: 16px;
}
then use it like this
<!-- language: lang-js -->
const formItemLayout =
formLayout === 'horizontal' ?
{
labelCol: {
span: 4,
style: {
"text-align": "left",
"font-size": "12px"
}
},
wrapperCol: {
span: 30,
},
} :
null;
<!-- end snippet -->
//then use it like this
<Form
{...formItemLayout}
layout={formLayout}
form={form}
initialValues={{
layout: formLayout,
}}
>
<Form.Item
label={"Full Name"}
name="username"
id="name"
style={{ display: "flex", flexDirection: "column" }}
defaultValue={name}
onChange={handleChange()}
rules={[
{
required: true,
message: 'Please input your name!',
},
]}
>
<Input />
</Form.Item>
</Form>

Categories

Resources