Save value in react js - javascript

I have a form with sub forms.
I have submit button for outer form but in the same time and for inner. The outer form works fine, it saves all data. but i can't get values from inner form clicking on
<Form.Item>
<Button type="primary" htmlType="submit">
Submit Inner
</Button>
</Form.Item>
Clicking on that i want to get values inside inner component in:
const onFinish = v => {
console.log("inner", v);
};
The subform code:
<Form.List onFinish={onFinish} name={[props.fieldKey, "inner"]}>
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => (
<div>
<Form.Item
// name={"aar"}
{...field}
name={[field.name, "innerName"]}
fieldKey={[field.fieldKey, "innerName"]}
key={index}
noStyle
>
<Input
placeholder="passenger name"
style={{ width: "60%" }}
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit Inner
</Button>
</Form.Item>
</div>
))}
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "60%" }}
>
<PlusOutlined /> Add field
</Button>
</div>
);
}}
</Form.List>
But when i click on this i get values in the outer form.
Question: How to get values from inner form clicking on Submit Inner button?
demo: https://codesandbox.io/s/wonderful-ives-o81ue?file=/SubForm.js
now i get:
expected result:

Related

Formik API : send different value in handleSubmit based on button click

I have the following code of a child component which is sending the form values to the parent when a user clicks .
Save and Continue button
Submit button
The Save and Continue button in the code is defined as follows:
<div className="form-field">
<Button size="large" variant="contained" color="primary" style={{marginLeft: '5px'}} type="submit">Save & Continue</Button>
</div>
When a user clicks Save and Continue button, I want to return requestStatuses: props.SimpleRequest && props.SimpleRequest.statusId || '10',.
However, when a user clicks the following Submit button:
<Button size="large" variant="contained" color="primary"
type="submit">Submit</Button>
I want to return props.SimpleRequest && props.SimpleRequest.statusId || '6',.
The default value for Status is 6 when a user interacts with the form and the dropdown is disabled so user can't change it. However, I want to send different values of it as I explained above based on different button clicks. Is it possible?
Minimal Code with relavent Formik form information is below:
const SimpleRequestForm = (props) => {
const {values, setFieldValue, touched, errors, isSubmitting, handleReset, handleChange} =
props;
const growl = React.createRef()
return (
<div>
<div id="formDiv">
<Growl ref={growl}/>
<Form className="form-column-3">
<div className="SimpleRequest-form">
<div className="form-field">
<CustomSelectField name="requestStatuses" disabled type="select" placeholder="Status"/>
</div>
<div className="form-field">
<CustomSelectField name="requestPrioritieses" type="select" value='Normal' placeholder="Priority"/>
</div>
<div className="form-field">
<CustomSelectField name="assignees" type="select" placeholder="Assignee"/>
</div>
<div className="form-field">
<Button size="large" variant="contained" color="primary" style={{marginLeft: '5px'}} type="submit">Save & Continue</Button>
</div>
</div>
<div className="btn-group-right">
<Button size="large" variant="contained" color="primary"
type="submit">Submit</Button>
<Button size="large" variant="contained" color="primary" onClick={handleReset}
style={{marginLeft: '5px'}} type="button">Reset</Button>
<Button size="large" variant="contained" color="primary" onClick={props.onCancel}
style={{marginLeft: '5px'}} type="button">Cancel</Button>
</div>
</Form>
</div>
</div>
)
};
export const SimpleRequestEnhancedForm = withFormik(
{
mapPropsToValues: props => {
return {
requestId: props.SimpleRequest && props.SimpleRequest.requestId || '',
requestStatuses: props.SimpleRequest && props.SimpleRequest.statusId || '6',
requestPrioritieses: props.SimpleRequest && props.SimpleRequest.priorityId || '3',
assignees: props.SimpleRequest && props.SimpleRequest.assigneeId || '',
}
},
validationSchema:validationSchema,
handleSubmit(values, {props, resetForm, setErrors, setSubmitting}) {
console.log("submit Simple Request Form....")
values.assets = JSON.parse(sessionStorage.getItem('uploadedFiles'));
props.handleSubmit(values)
setSubmitting(false)
},
setFieldValue(field, value, shouldVal) {
console.log('In setFieldValue')
},
displayName: 'Simple Request Form',
})(SimpleRequestForm)

Cannot enter value into MDEditor

When I run the program, I can't enter a value in the input, help me
const FormCommnent = ({ onChange, onSubmit, value }) => (
<div className="form-comment">
<MDEditor
value={value}
onChange={onChange}
name="content"
rows={4}
autoFocus={0}
preview='edit'
/>
<MDEditor.Markdown source={value} />
<Button htmlType="submit" onClick={onSubmit} >
Add Comment
</Button>
</div>
);

Set first fields open in a dynamic form

I have a dynamic form where users can add data. By default i want to set the form in this way:
How you can see, the first pair of input is open when user opens the application.
I made this by changing this:
const Demo = () => {
const onFinish = values => {
console.log("Received values of form:", values);
};
return (
<Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
<Form.List name="users">
{(fields, { add, remove }) => {
console.log(fields);
return (
<div>
{fields.map(field => (
<Space
key={field.key}
style={{ display: "flex", marginBottom: 8 }}
align="start"
>
<Form.Item
{...field}
name={[field.name, "first"]}
fieldKey={[field.fieldKey, "first"]}
rules={[{ required: true, message: "Missing first name" }]}
>
<Input placeholder="First Name" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, "last"]}
fieldKey={[field.fieldKey, "last"]}
rules={[{ required: true, message: "Missing last name" }]}
>
<Input placeholder="Last Name" />
</Form.Item>
<MinusCircleOutlined
onClick={() => {
remove(field.name);
}}
/>
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add field
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
to this:
const Demo = () => {
const onFinish = values => {
console.log("Received values of form:", values);
};
const firstDefaultOpen = {
name: 0,
key: 0,
isListField: true,
fieldKey: 0
};
return (
<Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
<Form.List name="users">
{(fields, { add, remove }) => {
console.log(fields);
return (
<div>
{fields.concat(firstDefaultOpen).map(field => (
<Space
key={field.key}
style={{ display: "flex", marginBottom: 8 }}
align="start"
>
<Form.Item
{...field}
name={[field.name, "first"]}
fieldKey={[field.fieldKey, "first"]}
rules={[{ required: true, message: "Missing first name" }]}
>
<Input placeholder="First Name" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, "last"]}
fieldKey={[field.fieldKey, "last"]}
rules={[{ required: true, message: "Missing last name" }]}
>
<Input placeholder="Last Name" />
</Form.Item>
<MinusCircleOutlined
onClick={() => {
remove(field.name);
}}
/>
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add field
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
Issue: But appears a problem when i try to add another input, because writing on first pair of inputs i can see the same text on the next inputs. Probably this is hapenening because of the same ids.
Question: How to set default open first pair of input as in the image using the code above?
demo: https://codesandbox.io/s/hungry-star-nu5ld?file=/index.js:235-2322
ps: i know that exists the next solution:
<Form initialValues={{ users: [""] }} name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
<Form.List name="users">
{(fields, { add, remove }) => {
console.log(fields);
return (
<div>
{fields.map(field => (
...
...
But i don't want this solution because i can't interact with <Form/> tag in my real application, so even this could be a solution, but i need another, like mine with concat() but of course to be workable.

Add unique keys for items in reactjs

I have the next application:
https://codesandbox.io/s/suspicious-murdock-87j13?file=/SubForm.js
<Form.List name="names">
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => {
console.log("m", field);
return (
<Form.Item
{...(index === 0
? formItemLayout
: formItemLayoutWithOutLabel)}
label={index === 0 ? "Passengers" : ""}
required={false}
key={index}
>
<Form.Item
{...field}
name={[field.name, "outer"]}
fieldKey={[field.fieldKey, "outer"]}
validateTrigger={["onChange", "onBlur"]}
rules={[
{
required: true,
whitespace: true,
message:
"Please input passenger's name or delete this field."
}
]}
noStyle
>
<Input
placeholder="passenger name"
style={{ width: "60%" }}
/>
</Form.Item>
<Form.Item
{...field}
name={[field.name, "outer1"]}
fieldKey={[field.fieldKey, "outer1"]}
validateTrigger={["onChange", "onBlur"]}
rules={[
{
required: true,
whitespace: true,
message:
"Please input passenger's name or delete this field."
}
]}
noStyle
>
<Input
placeholder="passenger name"
style={{ width: "60%" }}
/>
</Form.Item>
<Form.Item>
<InnerForm fieldKey={field.key} />
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined
className="dynamic-delete-button"
style={{ margin: "0 8px" }}
onClick={() => {
remove(field.name);
}}
/>
) : null}
</Form.Item>
);
})}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "60%" }}
>
<PlusOutlined /> Add field
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
When user click on Add field button, in console appears the warning:
Warning: Encountered two children with the same key, `0`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
Also this warning appears when i click on Add sub-field. I can't figure out why this warning appears.
Question: Why the above warning appears and how to remove it?
You have two Form.Item Component in your code, and they use same key index, try to use different key like 'item1' + index and 'item2' + index.
And, in your index.js file also have same problem.
Here is Demo forked from you: https://codesandbox.io/s/dark-darkness-xz0wf?file=/SubForm.js
As reactJs primary works on re rendering items every time you make a change the state of that component. It requires an unique key to track each and every item so that re-rendering can be optimized. Not all items needs to be re-render every time.
This warning essentially means that you have multiple items with same key names. In order to fix this you have to provide unique "key" attribute to each child component which is getting updated, components which can potentially trigger an re-render.
you don't need to use multiple times key={index} or key={"g"}
use once only.
Please try following
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, Button, Space } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '#ant-design/icons';
const Demo = () => {
const onFinish = values => {
console.log('Received values of form:', values);
};
return (
<Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
<Form.List name="users">
{(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, 'innerName']}
fieldKey={[field.fieldKey, 'innerName']}
>
<Input placeholder="passenger 1" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'innerName2']}
fieldKey={[field.fieldKey, 'innerName2']}
>
<Input placeholder="passenger 2" />
</Form.Item>
<MinusCircleOutlined
onClick={() => {
remove(field.name);
}}
/>
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add field
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, document.getElementById('container'));

How to redirect textfields enter command of going to form submit instead of button midway form?

I'm using material UI as my component library. I have a small dialog that has a "recover password" button placed somewhere inside the form. - I notice that after adding this button the "enter" command in the textfields becomes the onClick command of the buttons.
The form is simply like:
type PropTy = {
classes: any,
submit: (Event) => mixed;
handleClose: (Event) => mixed;
handleRequestPasswordRecover: (Event) => mixed;
};
function SigninForm(props:PropTy) {
const {classes, submit, handleClose, handleRequestPasswordRecover} = props;
const signinRef = React.createRef();
const actions = [
<Button
type="reset"
label="Reset"
color="secondary"
style={{ float: 'left' }}
key='reset'
>Reset</Button>,
<Button
label="Cancel"
color="primary"
onClick={handleClose}
key='cancel'
>Cancel</Button>,
<Button
type="submit"
label="Submit"
variant="contained"
color="primary"
key='submit'
autoFocus
>Login</Button>,
];
return (
<form className={classes.form}
onSubmit={submit}
ref={signinRef}
>
<FormControl margin="normal" required fullWidth>
<TextField id="username" name="username" autoComplete="username" autoFocus label={'Username'}/>
</FormControl>
<FormControl margin="normal" required fullWidth>
<div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'baseline'}}>
<FormLabel htmlFor="password">Password</FormLabel>
<button className={classes.linkButton} onClick={(e) => {
handleRequestPasswordRecover(e)
}}>{'Lost password?'}</button>
</div>
<Input
name="password"
type="password"
id="password"
autoComplete="current-password"
/>
</FormControl>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<div style={{ textAlign: 'right'}}>
{actions}
</div>
</form>);
}
The action that happens on "enter" is not "submit" as I expect - but rather the button's onClick event (handleRequestPasswordRecover). How do I redirect this?
You should set the type attribute of the button with the onClick={(e) => { handleRequestPasswordRecover(e)... to "button" (i.e. <button type="button"...).
The default type of buttons is submit.
Inside submit function you can call preventDefault();
const submit = (event)=>{ event.preventDefault(); }
You can write the below code in your html on form tag. So you can prevent the form submission on hit the enter key while focus on textfield.
<form className={classes.form}
onSubmit={submit}
ref={signinRef}
onKeyPress={(event) => {
if (event.key === "Enter") {
event.preventDefault();
}
}}>

Categories