How to get boolean data from API selected in a Dropdown (REACT)? - reactjs

I created a dropdown with "true" and "false" options. I get from my API all of my data in a table.
On update, I've got a form that gets the row data. With boolean values, it gets true/false just if I let the html type on "text".
I want to use the dropdown but at the moment it's static so it's always on "true".
How can I select the right value and update the change?
toSelectOption.js
export const trueFalse = [
{ label: "true", value: "Y" },
{ label: "false", value: "F" }
];
Update.jsx
renderTrueFalse() {
return trueFalse.map((item) => {
if (this.state.showKey === true) {
return (
<option value={item.value}>{item.label}</option>
);
}
});
}
//...
<Formik
initialValues={{
//...
showKey,
//...
}}
onSubmit={this.onSubmit}
//...
{
(props) => (
<Form>
//...
<Col md="3">
<FormGroup>
<label>Show Key</label>
<Field className="form-control" component="select"
name="showKey">
{this.renderTrueFalse()}
</Field>
</FormGroup>
</Col>
//...
<div className="d-flex justify-content-center">
<MDBBtn type="submit"
className="btn btn-outline-success waves-effect">Salva</MDBBtn>
</div>
</Form>
)
}
</Formik>
//...

I think that you are missing an onChange event handler on your <Field> component.
Try to add this:
Update.jsx
<Field className="form-control"
component="select"
name="showKey"
onChange={e => this.handleOnChange(e)}
>
and then below your function renderTrueFalse(), add this one:
handleOnChange = e => {
console.log('value->', e.target.value) // e.target.value is your output (Y or F) from the select option
// do whatever you wanna do here with the value from the option in this case ('Y' OR 'F')
}
Open your develop Tools (F12) and see that you are indeed receiving the updated value when you choose the right option.
Check this working on a sample with only React, here

Related

Selecting input element form of a react functional component

could u help a curious intern developer? ^^
I'm using the form inside a functional react component, there is 4 "fake pages" that Im controlling by buttons to hide/show the others input elements. Everytime the user changes the page by clicking in "Next Page" button Im calling a function to see if the inputs present on that page is correctly filled, If something is missing I wanna show an alert and focus (for example) to the corresponding input.
I already tried to use Jquery but got error saying that $(..) is not defined.
I read in some pages that I could use Refs to make this happen but yet in these pages says that its not indicated to use too much refs in a component, now Im wondering if there is another way to accomplish my goal.
Whats the best way to do this?
My code:
const handlePageChange = (e, pageNumber, action) => {
if(action === '+'){
if(pageNumber === '1'){
const nameArray = contactName.split('' );
if(nameArray.length < 2 || nameArray[1] == ''){
alert('Please inform your full name.');
//$("#contactName").focus();
}else{setPageNumber('2')}
}
}
}
return (
<div className="row">
<form onSubmit={handleSubmit} className="col s12">
{pageNumber==='1' &&
<div id='contact-section' className="row form-section">
<label className='active form-tittle'>Informações de Contato (1/4)</label>
<div className="input-field col s12 ">
<input id="contactName" type="text" className="validate"
value={contactName} onChange={e => setContactName(e.target.value)}
/>
<label className='active' htmlFor="contactName">Nome</label>
</div>
<div className="input-field col s12">
<input id="contactPhones" type="text" className="validate"
value={contactPhones} onChange={e => setContactPhones(e.target.value)}
/>
<label className='active' htmlFor="contactPhones">Telefone de Contato</label>
</div>
<div className="input-field col s12">
<input id="contactEmail" type="email" className="validate"
value={contactEmail} onChange={e => setContactEmail(e.target.value)}
/>
<label className='active' htmlFor="contactEmail">E-mail</label>
</div>
<div className='buttons-box'>
<a className="waves-effect waves-light yellow darken-2 btn" onClick={e=> handlePageChange(e, '1','+')}><i className="material-icons right">chevron_right</i>Next Page</a>
</div>
</div>}
In React, given the advent of JSX, you don't really need to use JQuery.
If you are planning to fully leverage the power of React, or maybe you're confused on why you don't really need JQuery, I suggest to read up on this article...
Refs provide a way to access DOM nodes or React elements created in
the render method.
Now, just taking a look at your code snippet, I suggest you take a different approach. Instead of wrapping all three of your "fake page" components in a form, think about having an entire form per "fake page" (three forms total if you have three pages). Note that you don't have to actually perform a form submit when they hit the next button, but you could just intercept that event, perform validation, accumulate the values into a React context or higher level hook, and render the next page.
With React, (just like other things) you have to learn to think in React. Make sure that you hash out different approaches when you run into problems like this, because if your code gets too spaghetti-like with a bunch of refs pointing everywhere, there is likely a simpler, more elegant approach.
If you are using React.js, I would be inclined to suggest formik or some framework to abstract away some of the complexity of dealing with form state and validation. It will make your life a whole lot easier. I personally use Ant Design's Steps with each Step containing a form. You can always shell out to scss, tailwindcss, less, or the style prop to override Ant Design's classic styles.
Here is an untested example I threw together using Ant Design just so you can understand conceptually where I am coming from.
import React, { useState } from "react";
import { Form, Button, Divider, Steps, message } from "antd";
import { PageOne, PageTwo, PageThree } from "./Pages";
const { Step } = Steps;
function StepperForm() {
const [current, setCurrent] = React.useState(0);
const [globalValues, setGlobalValues] = useState([]);
const [PageOneForm] = Form.useForm();
const [PageTwoForm] = Form.useForm();
const [PageThreeForm] = Form.useForm();
const steps = [
{
title: "Page One",
content: <PageOne formRef={PageOneForm} />,
},
{
title: "Page Two",
content: <PageTwo formRef={PageTwoForm} />,
},
{
title: "Page Three",
content: <PageThree formRef={PageThreeForm} />,
},
];
const prev = () => {
setCurrent(current - 1);
var it = globalValues;
it.pop();
setGlobalValues(it);
};
const next = () => {
switch (current) {
case 0:
PageOneForm.validateFields()
.then((values) => {
setGlobalValues([values]);
setCurrent(current + 1);
})
.catch((errorInfo) => {
message.error(
"You cannot move on until all " +
errorInfo.errorFields.length +
" errors are resolved."
);
});
break;
case 1:
PageTwoForm.validateFields()
.then((values) => {
var it = onBoardValues;
it.push(values);
setGlobalValues(it);
setCurrent(current + 1);
})
.catch((errorInfo) => {
message.error(
"You cannot move on until all " +
errorInfo.errorFields.length +
" errors are resolved."
);
});
break;
case 2:
PageThreeForm.validateFields()
.then((values) => {
var it = onBoardValues;
it.push(values);
setGlobalValues(it);
setCurrent(current + 1);
//call api.
})
.catch((errorInfo) => {
message.error(
"You cannot move on until all " +
errorInfo.errorFields.length +
" errors are resolved."
);
});
break;
}
};
return (
<>
<Steps current={current}>
{steps.map((item) => (
<Step key={item.title} title={item.title} />
))}
</Steps>
<Divider />
<div>{steps[current].content}</div>
<div>
{current > 0 && <Button onClick={() => prev()}>Previous</Button>}
{current < steps.length - 1 && (
<Button onClick={() => next()}>Next</Button>
)}
{current === steps.length - 1 && (
<Button onClick={() => next()}>Done</Button>
)}
</div>
</>
);
}
Where the PageOne component might look like
import React from "react";
import { Form, Input, Row, Col } from "antd";
export function PageOne(props) {
const [form] = Form.useForm();
return (
<div>
<Form
size={"medium"}
form={props.formRef}
name="PageOne"
label="left"
layout="vertical"
>
<Row>
<Col>
<Form.Item
validateTrigger="onBlur"
name="FirstName"
label={"First Name"}
rules={[
{
required: true,
message: "Please enter your first name.",
whitespace: true,
},
]}
>
<Input />
</Form.Item>
</Col>
<Col>
<Form.Item
validateTrigger="onBlur"
name="LastName"
label={"Last Name"}
rules={[
{
required: true,
message: "Please enter your last name.",
whitespace: true,
},
]}
>
<Input />
</Form.Item>
</Col>
</Row>
<Row>
<Col>
<Form.Item
validateTrigger="onBlur"
name="EmailAddress"
label="Primary E-mail"
rules={[
{
type: "email",
message: "Enter a valid E-mail.",
},
{
required: true,
message: "Please enter your E-mail.",
},
]}
>
<Input />
</Form.Item>
</Col>
<Col>
<Form.Item
validateTrigger="onBlur"
name="PhoneNumber"
label="Phone Number"
hasFeedback
rules={[
{
required: true,
message: "Phone number required for MFA.",
},
({ setFieldsValue }) => ({
validator(_, value) {
if (!value) {
return Promise.reject();
}
value = value.toString();
value = value.replace(/[^\d]/g, "");
setFieldsValue({ PhoneNumber: value });
if (value.length < 10) {
return Promise.reject(
"Phone number can't be less than 10 digits"
);
}
if (value.length > 10) {
return Promise.reject(
"Phone number can't be more than 10 digits"
);
}
return Promise.resolve();
},
}),
]}
>
<Input />
</Form.Item>
</Col>
</Row>
<Row>
<Col>
<Form.Item
validateTrigger="onBlur"
name="Password"
label="Password"
rules={[
{
required: true,
message: "Please enter your password.",
},
]}
hasFeedback
>
<Input.Password />
</Form.Item>
</Col>
<Col>
<Form.Item
validateTrigger="onBlur"
name="ConfirmPassword"
label="Confirm Password"
dependencies={["password"]}
hasFeedback
rules={[
{
required: true,
message: "Please confirm your password.",
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue("Password") === value) {
return Promise.resolve();
}
return Promise.reject(
"The two passwords that you entered do not match."
);
},
}),
]}
>
<Input.Password />
</Form.Item>
</Col>
</Row>
</Form>
</div>
);
}
As you can see, component frameworks help you out a lot (even with form validation). I personally like how ANTD has it included. If you are just learning, there is some value in re-creating the wheel for learning's sake, but after a while, it is important to learn that you don't need to every time.
P.S. Next time, include your complete component code formatted. It makes it hard for us to read and comprehend otherwise.

How to reset a react-select single-input with Formik with reset button

I am relatively new to React and especially new to both react-select and Formik. I have a form that has an Input component and three Select components. The input as well as the two selects that use isMulti for multiple selected options at once clear just fine when I use just a basic reset button, but the single select component does not. If I check what the values are they are empty, but the UI does not reflect this change. I have tried:
utilizing resetForm(), setting it to the initialValues as well as an empty object.
using onReset and implicitly calling resetForm from there.
using a few different variations of setFieldValue
I thought it might be the way my initialValues were set up, but at this point I am just going in circles and hoping a more seasoned eye can pick up on this.
(PS- the example in the docs shows you how to use React-Select with Formik with a reset button, but it does not give an example of a non-multi select.)
The single select has a name of 'paid', and I have include the object which I believe is correct using a value and a label property
simplified sandbox. desired behavior: clicking 'reset' will reset the option to the initialValues and show the placeholder text in the UI.
https://codesandbox.io/s/peh1q
const costOptions = [
{ value: 'true', label: 'Paid' },
{ value: 'false', label: 'Free' },
];
Resources.propTypes = {
initialValues: shape({
category: array,
q: string,
languages: array,
paid: string,
}),
};
Resources.defaultProps = {
initialValues: {
category: [],
q: '',
languages: [],
paid: '',
},
};
<Formik
enableReinitialize
initialValues={initialValues}
onSubmit={(values, actions) => {
handleSubmit(values, actions);
actions.setSubmitting(true);
}}
>
{({ isSubmitting }) => (
<Form>
<Field
data-testid={RESOURCE_SEARCH}
disabled={isSubmitting}
type="search"
name="q"
label="Search Keywords"
component={Input}
/>
<div className={styles.formContainer}>
<div className={styles.selectColumn}>
<Field
isDisabled={isSubmitting}
isMulti
placeholder="Start typing a category..."
label="By Category"
name="category"
options={allCategories}
component={Select}
/>
</div>
<div className={styles.selectColumn}>
<Field
isDisabled={isSubmitting}
placeholder="Resource cost..."
label="By Cost"
name="paid"
options={costOptions}
component={Select}
/>
</div>
<div className={styles.selectColumn}>
<Field
isDisabled={isSubmitting}
placeholder="Start typing a language..."
isMulti
label="By Language(s)"
name="languages"
options={allLanguages}
component={Select}
/>
</div>
</div>
<div className={styles.buttonGroup}>
<Button disabled={isSubmitting} type="submit">
Search
</Button>
<Button disabled={isSubmitting} type="reset">
Reset
</Button>
</div>
</Form>
)}
</Formik>
So nothing I needed to fix was actually in the code I posted (learning point taken) but it was in the codesandbox.
Select component being used in Formik looks like this:
import React from 'react';
import {
arrayOf,
bool,
func,
number,
object,
objectOf,
oneOfType,
shape,
string,
} from 'prop-types';
import { ErrorMessage } from 'formik';
import Alert from 'components/Alert/Alert';
import Label from 'components/Form/Label/Label';
import ThemedReactSelect from './ThemedReactSelect';
import styles from './Select.module.css';
Select.propTypes = {
field: shape({
name: string.isRequired,
value: oneOfType([string.isRequired, arrayOf(string.isRequired).isRequired]),
}).isRequired,
form: shape({
// TODO: Resolve why multiselects can end up with touched: { key: array }
// see ThemedReactSelect as well
// touched: objectOf(bool).isRequired,
touched: object.isRequired,
errors: objectOf(string).isRequired,
setFieldTouched: func.isRequired,
setFieldValue: func.isRequired,
}).isRequired,
hasValidationStyling: bool,
id: oneOfType([string, number]),
isLabelHidden: bool,
isMulti: bool,
label: string.isRequired,
options: arrayOf(shape({ label: string.isRequired, value: string.isRequired }).isRequired)
.isRequired,
};
Select.defaultProps = {
hasValidationStyling: true,
id: undefined,
isLabelHidden: false,
isMulti: false,
};
export default function Select({
field: { name, value: fieldValue },
form: { errors, setFieldTouched, setFieldValue, touched },
hasValidationStyling,
id,
isLabelHidden,
isMulti,
label,
options,
...props // disabled, placeholder, etc.
}) {
/**
* #description handle changing of non-multi select
* #param {string} selected
*/
const onChangeSingle = selected => {
setFieldValue(name, selected.value);
};
/**
* #description handle changing of multi select
* #param {string[]} selectedArray
*/
const onChangeMulti = selectedArray => {
if (selectedArray) {
setFieldValue(
name,
selectedArray.map(item => item.value),
);
} else {
setFieldValue(name, []);
}
};
/**
* #description Return the selected value as a string
* #returns {string}
*/
const getValueFromSingle = () => {
return options.find(option => option.value === fieldValue);
};
/**
* #description Return an array of selected values for multi selects
* #returns {string[]}
*/
const getValueFromMulti = () => {
return options.filter(option => fieldValue.includes(option.value));
};
const handleBlur = () => {
setFieldTouched(name);
};
const hasErrors = Boolean(errors[name]);
// handlers and value depend on whether or not select allows for multiple selections.
const value = isMulti ? getValueFromMulti() : getValueFromSingle();
const onChangeHandler = isMulti ? onChangeMulti : onChangeSingle;
return (
<div className={styles.field}>
<Label for={name} isHidden={isLabelHidden}>
{label}
</Label>
<div className={styles.selectFeedbackGrouping}>
<ThemedReactSelect
{...props}
hasErrors={hasErrors}
hasValidationStyling={hasValidationStyling}
isTouched={touched[name]}
id={id || name}
isMulti={isMulti}
name={name}
onBlur={handleBlur}
onChange={onChangeHandler}
options={options}
value={value}
/>
<ErrorMessage
name={name}
render={message => {
return hasErrors ? (
<Alert className={styles.errorMessage} type="error">
{message}
</Alert>
) : null;
}}
/>
</div>
</div>
);
}
Firstly, handle the null value that gets passed in handleOnChange when an input has isClearable={true} and you click the 'X' to clear the select
const onChangeSingle = selected => {
setFieldValue(name, selected === null ? '' : selected.value);
};
Then, give a fallback for the field value (in the ThemedReactSelect above)
<ThemedReactSelect
{...props}
hasErrors={hasErrors}
hasValidationStyling={hasValidationStyling}
isTouched={touched[name]}
id={id || name}
isMulti={isMulti}
name={name}
onBlur={handleBlur}
onChange={onChangeHandler}
options={options}
value={value || ''}
/>
and now the single selects work just like the multis when form is reset.
Have you tried adding the isClearable prop to the single value dropdown?
<Formik
enableReinitialize
initialValues={initialValues}
onSubmit={(values, actions) => {
handleSubmit(values, actions);
actions.setSubmitting(true);
}}
>
{({ isSubmitting }) => (
<Form>
//...Other Formik components
<div className={styles.selectColumn}>
<Field
isClearable={true} // <-- added this
isDisabled={isSubmitting}
placeholder="Resource cost..."
label="By Cost"
name="paid"
options={costOptions}
component={Select}
/>
</div>
<div className={styles.selectColumn}>
<Field
isDisabled={isSubmitting}
placeholder="Start typing a language..."
isMulti
label="By Language(s)"
name="languages"
options={allLanguages}
component={Select}
/>
</div>
</div>
<div className={styles.buttonGroup}>
<Button disabled={isSubmitting} type="submit">
Search
</Button>
<Button disabled={isSubmitting} type="reset">
Reset
</Button>
</div>
</Form>
)}
</Formik>

Clear a field's value on input clear in react-final-form

I'm using a custom component with react-final-form. On input change it sets the value to the address field. But when the input is cleared it doesn't update the value of the field. So I'm trying to do it with form mutators.
I have already added a mutator for clearing the field:
mutators={{
clear: ([address], state, { changeValue }) => {
changeValue(state, "address", () => undefined);
}
}}
I tried to add it to my custom onChange function, but it doesn't work.
onChange={event =>
props.input.onChange !== undefined
? props.input.onChange({ value: event })
: form.mutators.clear
}
Or maybe this can be done without mutators at all? I would really appreciate your help. Here is a live example (clearing the field works only on the button click as onClick={form.mutators.clear}).
You can just call form.change('address', undefined) at any time that you'd like to clear the value.
All the default callback are handle by the component. If you want to do a clear with a button click, you can create a custom component and use native callback methods do your thing.
onChange = (event) => {
this.setState({
address:event.target.value
});
}
onClear = () => {
this.setState({
address:''
});
}
<div>
<Field name="address">
<div>
<input
value={this.state.address}
onChange={this.onChange}
/>
</div>
</Field>
<button onClick={this.onClear}>Clear</button>
</div>
The problem is not with the react-final-form in your code, it is due to the react-da data, I have played a lot around your code within 1 day, and checked reset is working with fine with the react-final-form
Just update your render with this code and see reset is working absolutely fine. Yeah! the problem is with react da data. I am not sure about what it does due to less official information for this package.
<div className="App">
<h2>Dadata test</h2>
<Form
mutators={{
clear: ([address], state, { changeValue }) => {
changeValue(state, "address", () => undefined);
}
}}
onSubmit={onSubmit}
render={({ form, handleSubmit, pristine, invalid, values, errors }) => (
<form onSubmit={handleSubmit} noValidate>
<Field name="address" component="input" />
{/* {props => (
<div>
<ReactDadata
token="d19c6d0b94e64b21d8168f9659f64f7b8c1acd1f"
onChange={event =>
props.input.onChange !== undefined
? props.input.onChange({ value: event })
: form.mutators.clear
}
/>
</div>
)}
</Field> */}
<button type="submit" disabled={invalid}>
Submit
</button>
<button type="button" onClick={form.reset}>
Clear
</button>
<Fields names={["address"]}>
{fieldsState => (
<pre>{JSON.stringify(fieldsState, undefined, 2)}</pre>
)}
</Fields>
</form>
)}
/>
</div>
Hope it will help you to resolve the problem.

Formik form not updating fields upon edit

I've been trying to rewrite my beginner form in React to use Formik.
I've gotten to the state that the form is being rendered, however, for some reason, I can't update the fields. It's clear that I made a mistake somewhere that prevents Formik from updating the state. What am I missing?
An example form component:
export const TextBox: React.SFC<FieldProps<any> & CustomFormElementProps> = ({
field, // { name, value, onChange, onBlur }
form: { touched, errors },
loading,
...props
}) => (
<div className="row form-group" key={field.name}>
<label className="col-sm-2 control-label">
<ReactPlaceholder showLoadingAnimation ready={!loading} type="text" rows={1} className="control-label">
{props.label}
</ReactPlaceholder>
</label>
<div className="col-sm-10">
<ReactPlaceholder showLoadingAnimation ready={!loading} type="text" rows={1} className="form-control">
<input type="text"
disabled={props.disabled}
className="form-control"
id={field.name}
onChange={field.onChange}
onBlur={field.onBlur} {...props} />
{touched[field.name] && errors[field.name] && <span className="text-danger">{errors[field.name]}</span>}
</ReactPlaceholder>
</div>
</div>
);
The form is initialized in another component (which acts as a page template for the website);
renderFormElements() {
var formFields = this.props.detailsElements.map((item) => {
switch (item.type) {
case FormElementType.TextLine:
return <TextLine
name={item.name}
label={item.label}
disabled={!this.state.editMode}
loading={item.loading}
value={item.defaultValue}
key={'TextBox_' + item.name}
/>
case FormElementType.TextBox:
return <Field
type="text"
name={item.name}
label={item.label}
component={InputElements.TextBox}
disabled={!this.state.editMode}
loading={item.loading}
value={item.defaultValue}
key={'TextBox_' + item.name}
/>
case FormElementType.DropDown:
return <Field
name={item.name}
label={item.label}
component={InputElements.DropDown}
disabled={!this.state.editMode}
loading={item.loading}
value={item.defaultValue}
options={item.options}
key={'DropDown_' + item.name}
/>
case FormElementType.RadioGroup:
return <Field
type="radio"
name={item.name}
label={item.label}
component={InputElements.RadioGroup}
disabled={!this.state.editMode}
loading={item.loading}
value={item.defaultValue}
options={item.options}
key={'RadioGroup' + item.name}
/>
}
});
var initialValues:{ [k: string]: any } = {};
this.props.detailsElements.map((item) => {
initialValues[item.name] = item.defaultValue;
})
console.log(initialValues);
var formSection =
(<Formik initialValues={initialValues} onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}>
<Form key="mainForm">
{formFields}
</Form>
</Formik>)
return formSection;
I was assuming that the onChange event handler was taken care of by Formik, and that, if I didn't want to do special stuff, I did not need to provide anything to this.
What am I missing here?
Thanks!
your formFields function gets all of Formik props goodies.
it contains handleChange - use this handler as your on change.
Also, make sure the field "id" is the same as the values key.
const {
values,
touched,
errors,
dirty,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
} = this.props;
<FormControl
id="username"
required
placeholder="Enter Username"
value={values.username}
error={touched.username && errors.username}
onChange={handleChange}
onBlur={handleBlur}
/>
try putting the name attribute in the input element
name is what you got from field.name

How do I combine `final-form-calculate` with `final-form-array`

I have a form which uses react-final-form-array in order to have many "Attendees". I'm wanting each of the Attendee.Email inputs to do a web lookup and then set the Attendee.FirstName and Attendee.Surname based off the result.
I'm not sure how this should be expressed with a final-form-calculate decorator. Specifically, I don't know how to reference the individual form item within the array.
Here's what I've got as a start:
const MyForm = props => {
const calculator = createDecorator(
{
field: 'Attendees.Email', // <-- this needs to happen for each Email
updates: {
// ... do some lookups and set FirstName and Surname based off database query
Attendees.FirstName: (email, allValues) =>
someLookup(email).FirstName
}
},
);
const submit = values => {
console.log(values);
};
return (<Form onSubmit={submit}
mutators={{
...arrayMutators,
}}
decorators={[calculator]}
render={({handleSubmit, pristine, invalid, mutators: {push, pop}}) => {
return (
<form onSubmit={handleSubmit}>
<fieldset>
<legend>Attendees</legend>
<div className="fieldset">
<p><Button bsStyle="primary" onClick={() => push('Attendees', undefined)}>
Add attendee
</Button></p>
<FieldArray name="Attendees">
{({fields}) =>
fields.map((name, index) => (
<div key={name}>
<label>Attendee #{index + 1} {index > 0 && <span
onClick={() => {
const attendee = fields.remove(index);
}}
style={{cursor: 'pointer'}}
role="img"
aria-label="delete">❌</span>}</label>
<Field
name={`${name}.Email`}
component={TextField}
label="Email address"
validate={required}
/>
<Field
name={`${name}.FirstName`}
component={TextField}
label="First name"
validate={required}
/>
<Field
name={`${name}.Surname`}
component={TextField}
label="Surname"
validate={required}
/>
</div>
))}
</FieldArray>
</div>
</fieldset>
<Button type="submit" bsStyle="primary"
disabled={invalid}>Next</Button>
</form>
);
}}
/>);
};
export default MyForm;
Took me a bit of hunting but it's actually pretty simple - from the website i noticed they have it listed (but not clearly)
So for my case, i just picked up the name and changed the last part of the text to reflect the object property i wanted to modify.
Below, i use regex to match a field, then replace the last part of the name value to match a different field (stored in fieldName) and then return an array containing the new field i am changing and the new value.
{
field: /fields\[\d+\]\.field\.text/, // when a field matching this pattern changes...
updates: (value, name, allValues) => {
console.log('Update called', value, name);
const fieldName = name.replace('.text', '.name');
return {
[fieldName]: value.replace(/\W+/gi, '-').toLowerCase()
};
}
}

Resources