So, I would like to acess the data from Form outside him, for example, I have multiple forms in only a page:
<Form
validate={validate}
onSubmit={ (values, props) => props.reset() }
render={
({handleSubmit, invalid, ...props}) => {
return(
<form onSubmit={handleSubmit}>
...
</form>
)
}}
</Form>
<Form
validate={validate}
onSubmit={ (values, props) => props.reset() }
render={
({handleSubmit, invalid, ...props}) => {
return(
<form onSubmit={handleSubmit}>
...
</form>
)
}}
</Form>
//And I want check if all forms are valid, for example:
<button disable={ form1.invalid || form2.invalid }></button>
Someone have a idea about that?
I need to access form instance too to pass new values from api calls, disable fields calculate currencies on input event if i call from calculate it work one step latter.
Steps:
1. Have form with initial values
1.1 Need update values from api calls like calculate currencies
Optional First form can pass values that calls another form. Like starting form to declare second one
2 Pass submit values to api
2.1 Response values must rebind all form values and disable fields
3 Submit again just for confirm, form must stay same state
4 After success just horray, procces end
Thanks for response me, but I don't get it.
Can you explain with example?
I'm tried use final-form to don't need use redux(redux-form), but I'm thinking that will be more complex than I imagined
Create element(import from library) inside form
This is form render options render={({handleSubmit, form, submitting, pristine, values})
in function fnName you will access form functions and values this will work on every change, but then i change value in this function code start loop
Nice, I did it:
export const myForm = ({subscription, ...props}) => {
return(
<Form
onSubmit={(val)=> console.log(val)}
subscription={subscription}
render={({handleSubmit}) => (
<form onSubmit={handleSubmit}>
....
<FormSpy
subscription={{values: true, valid: true}}
onChange={(state) => {
const {values, valid} = state
props.exposeValues({values, valid})
}} />
</form>
)}
/>
)
}
Work very well for me, thanks dude, cya
I have a slightly different approach to this:
// in someForm.js
export const Form = ({setForm, onSubmit}) => (
<FinalForm
onSubmit={onSubmit}
render={({form, ...props}) => {
setForm(form)
return <form>...</form>
}/>
)
// in formMaster.js
const forms = {}
const setForm = formName => form => {forms[formName] = form}
const gatherFormData = async () => {
let formData = {}
for(let form of forms){
formData = Object.assign(form, await form.submit()) // onSubmit must be promise
}
return formData
}
const App = () => (
<Form onSubmit={gatherData} setForm={setForm('someForm')}/>
)
This allows you to reference the form from the master, submit everything at once. As a bonus, you can reset the forms using a basic forms.map(form => form.reset())
I needed more fine grained control (basically building a custom form generator using rff), so I had to go with ref and forwardRef.
// parent component / consumer of my library
class ParentComponent extends React.Component {
constructor(props)
// ...
this.formRef = React.createRef();
}
goToStep(step) {
const { history } = this.props;
const { form } = this.formRef.current;
const { dirty } = form.getState();
if (dirty) {
form.reset();
}
history.replace(step);
}
render() {
return (
<MyFormGenerator
ref={this.formRef}
{...props}
/>
)
}
}
// my library component
class FormGenerator extends React.Component {
// ...
render() {
return (
<Form
ref={this.props.forwardedRef}
{...formProps}
render={() => (
// ...
)}
/>
)
}
}
// wrap component in 'forwardRef` callback before exporting.
const FormGeneratorForwardRef = React.forwardRef((props, ref) => (<FormGenerator forwardedRef={ref} {...props} />));
export default FormGeneratorForwardRef;
In the Parent component we initialize a ref with createRef, and then in my library component we give it the ability to pass a ref to the form by wrapping the component with the forwardRef callback.
This gives me the entire form api available to the parent, and we are using it for all sorts of situations in addition to the example I provided here.
In your case, without that intermediate component (my library component), you can omit all of the forwardRef logic, and just create a ref and pass it to the Form component. That will do the trick.
In the case where you have multiple forms, it's just a matter of rinse and repeat.
I'll admit that its difficult to parse what is happening, but keep in mind that refs and forwardRef are supposed to be reserved for the rarest of use cases. In fact this is the first time I have had to do this in 3 years of React programming.
Nice, I did it:
export const myForm = ({subscription, ...props}) => { return( <Form onSubmit={(val)=> console.log(val)} subscription={subscription} render={({handleSubmit}) => ( <form onSubmit={handleSubmit}> .... <FormSpy subscription={{values: true, valid: true}} onChange={(state) => { const {values, valid} = state props.exposeValues({values, valid}) }} /> </form> )} /> ) }Work very well for me, thanks dude, cya
could you show me your code, please!, i don't know how to apply it. thanks
I need to check form data within a button click. I have a status field which contains the current workflow status. In one workflow step I need to read an array of data from the form and create an new record on another API endpoint.
How do I access form data as a structure?
I need to check form data within a button click. I have a status field which contains the current workflow status. In one workflow step I need to read an array of data from the form and create an new record on another API endpoint.
How do I access form data as a structure?
Can you show for us the code snippet? Do you can put on https://codesandbox.io/s/ ?
https://codesandbox.io/s/oq52p6v96y
in calculation you can access all data and do what you want on any field changes
https://codesandbox.io/s/32r824vxy1
_
_
form={form(from form props)}
values={values(from form props)}
...etc
/>_
in spy you can access all data and pass form props to custom component with life cycles. Where is and more options like bind form by id and get instance
Check this and take best solution
Hello guys!
@jweatherby In my case I use same solution with setForm(form), but it reduces performance. It lead to component rerender. Did you find some other ways to get form instance outside?
@jsrhodes15 Did your solution work in react-final-form v6 ? I can't get it work
// useConstant.js
import { useRef } from 'react';
export default function useConstant(init) {
const initiated = useRef(false);
const ref = useRef(undefined);
if (!initiated.current) {
initiated.current = true;
ref.current = init();
}
return ref.current;
}
import { createForm } from 'final-form';
function MyComponent() {
// `form` can also come from props, if needed
const form = useConstant(() => createForm({
initialValues,
onSubmit
}));
// use your form...
return (
<Form
form={form}
render={() => {
// You're <form />
}}
/>
);
}
Most helpful comment
Nice, I did it:
Work very well for me, thanks dude, cya