Closed andrewringler closed 5 years ago
Using version 0.2.2, you can create a custom container renderer for the Autosave component as follows:
import _ from 'lodash'
import React from 'react';
import { Element } from '@flipbyte/formik-json';
class Autosave extends React.Component {
state = {
isSaving: false,
}
componentWillReceiveProps(nextProps, nextContext) {
if (!_.isEqual(nextProps.formik.values, this.props.formik.values)) {
this.save()
}
}
save = _.debounce(() => {
this.setState({ isSaving: true, saveError: undefined })
this.props.config.onSave(this.props.formik.values)
.then(
() => this.setState({ isSaving: false, lastSaved: new Date() }),
() => this.setState({ isSaving: false, saveError })
)
}, 300);
render() {
const { name, elements } = this.props.config;
return (
<React.Fragment>
{ _.map(elements, ( element, key ) => (
<Element key={ key } config={ element } />
)) }
</React.Fragment>
);
}
}
export default Autosave;
Your form schema object should look something like this:
{
...your top level form renderer,
elements: {
autosave: {
id: 'autosave',
type: 'container',
renderer: Autosave,
onSave: values => new Promise((resolve) => {
resolve('saved');
}),
elements: {
...your elements
}
}
}
}
Thank you for the extremely quick response and for rolling out a new release. Yes, this solution works well for me.
Here is the final AutoSave.js
I ended up using:
import React from 'react';
import { Element } from '@flipbyte/formik-json/lib';
import _ from 'lodash';
// https://github.com/flipbyte/formik-json-schema/issues/19
class AutoSave extends React.Component {
state = {
isSaving: false,
saveError: null
}
componentWillReceiveProps(nextProps, nextContext) {
if (!_.isEqual(nextProps.formik.values, this.props.formik.values)) {
this.save()
}
}
save = _.debounce(() => {
this.setState({ isSaving: true, saveError: undefined })
this.props.config.onSave(this.props.formik.values)
.then(() => this.setState({ isSaving: false, lastSaved: new Date() }))
.catch((saveError) => this.setState({ isSaving: false, saveError: saveError }))
}, this.props.debounce)
render() {
const { elements } = this.props.config;
return (
<React.Fragment>
{ _.map(elements, ( element, key ) => (
<Element key={ key } config={ element } />
)) }
</React.Fragment>
);
}
}
export default AutoSave;
My form component looks something like the following. Note that i'm using the formik-json-schema
registry so that I can reference AutoSave
by name, since I am actually pulling the form specification in as JSON from a server API. I am also binding my save function to the form spec in componentDidMount
. I didn't show render, but its similar to the formik-json-schema
examples.
import React, { Component } from 'react';
import { Form, registry } from '@flipbyte/formik-json';
import AutoSave from './AutoSave';
const DEBOUNCE_TIME_MS = 300;
class Survey extends Component {
constructor(props) {
super(props);
registry.registerContainer('autosave', AutoSave);
}
componentDidMount() {
this.props.surveySpec.elements.autosave.onSave = values => this.putDataToDatabasePromise(values);
this.props.surveySpec.elements.autosave.debounce = DEBOUNCE_TIME_MS;
}
putDataToDatabasePromise(values) {
return axio.put …
}
…
}
export default Survey;
And my form JSON string looks something like:
{
id: "survey1",
label: "Survey 1",
type: "container",
renderer: "form",
elements: {
question1: {
type: "field",
renderer: 'textarea',
name: "question1",
label: "Question 1",
formGroupClass: "group",
},
submit: {
type: "field",
renderer: "button",
name: "submit",
label: "Submit",
buttonType: "submit"
},
autosave: {
id: 'autosave',
type: 'container',
debounce: 300,
renderer: 'autosave',
onSave: () => console.error('you must set onSave function in parent component')
}
}
}
I am trying to auto-save the Form I am generating with
formik-json-schema
. I have instructions for how to do this with just formik, Auto-saving forms #172 and more specifically I am following the gist here, but I am not sure how to adapt this to work withformik-json-schema
.With this approach a new component is created called
<AutoSave>
which is rendered as a child of<Form>
. I am not sure withformik-json-schema
however how I would modify the render or the children ofForm
to add the<AutoSave>
component. Is there a way to append arbitrary children to the form rendered byformik-json-schema
? Or is there an approach to implementing auto-save that might make more sense?Thanks,
Andrew