Skip to content

Instantly share code, notes, and snippets.

@michieldewilde
Created April 18, 2018 10:27
Show Gist options
  • Save michieldewilde/d7c5399e445bf8d1965aafe4f3162adb to your computer and use it in GitHub Desktop.
Save michieldewilde/d7c5399e445bf8d1965aafe4f3162adb to your computer and use it in GitHub Desktop.
Dialogs
import React from 'react'
import PropTypes from 'prop-types'
import { Formik } from 'formik'
import Dialog, {
DialogActions,
DialogContent,
DialogContentText,
DialogTitle
} from 'material-ui/Dialog'
import Button from 'material-ui/Button'
class FormDialog extends React.Component {
static propTypes = {
opener: PropTypes.func.isRequired
}
state = {
open: false
}
/**
* The dialog can serve many purposes by opening with a completely new state
* this should be validated eventually, but for now newState should have:
*
* title: string
* contentText: string
* validationSchema: yup schema object
* initialValues: formik initialValues
* render: formik render prop
* onSubmit: formik/dialog submit handler
*/
handleOpen = newState => {
this.setState(() => ({
...newState,
open: true
}))
}
handleClose = () => {
this.setState({
open: false
})
}
/**
* Calls the onSubmit passed via handleOpen with the
* formik submit args and the dialog close function
* (values, options: { setSubmitting, setErrors }, handleClose)
*/
handleSubmit = (...formikSubmitArgs) => {
this.state.onSubmit(...formikSubmitArgs, this.handleClose)
}
render () {
const {
open,
title,
contentText,
validationSchema,
initialValues,
render
} = this.state
return (
<div>
{this.props.opener(this.handleOpen)}
<Dialog open={open} onBackdropClick={this.handleClose}>
<DialogTitle>{title}</DialogTitle>
<Formik
validationSchema={validationSchema}
initialValues={initialValues}
onSubmit={this.handleSubmit}
render={formikProps => {
const { handleSubmit, isSubmitting } = formikProps
return (
<form onSubmit={handleSubmit}>
<DialogContent>
<DialogContentText>{contentText}</DialogContentText>
{render(formikProps)}
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose}>Cancel</Button>
<Button
type='submit'
color='secondary'
disabled={isSubmitting}
>
Submit
</Button>
</DialogActions>
</form>
)
}}
/>
</Dialog>
</div>
)
}
}
export default FormDialog
So the opener is a button that opens the dialog to create a screenshot.
I want to reuse that modal for editing a screenshot as well.
That will be done in a parent view by clicking on a item in a list.
How do I open the modal from outside of the FormDialog without using something like a global state manager?
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import yup from 'yup'
import {
FormDialog,
FormikTextInput as TextInput,
FormikFileUploadInput as FileUploadInput
} from 'components'
import Button from 'material-ui/Button'
import { card } from '../../../styles'
const schema = yup.object().shape({
caption: yup.string().required('This is a required field'),
image: yup.mixed().required()
})
class ScreenshotDialog extends Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired
}
static defaultProps = {
screenshot: null
}
handleOpen = openWithState => () => {
const { screenshot } = this.props
const title = screenshot ? 'Edit Screenshot' : 'New Screenshot'
openWithState({
title,
contentText: 'Add a screenshot with a descriptive caption',
initialValues: {
caption: screenshot ? screenshot.caption : '',
image: screenshot ? [screenshot.image] : []
},
validationSchema: schema,
render: this.renderFields,
onSubmit: this.props.handleSubmit
})
}
renderFields = formikProps => (
<fieldset style={{ ...card }}>
<TextInput
formikProps={formikProps}
label='Caption'
field='caption'
autoFocus
/>
<FileUploadInput
formikProps={formikProps}
label='Image'
field='image'
multiple={false}
/>
</fieldset>
)
opener = openWithState => (
<Button
raised
className='fr'
color='primary'
onClick={this.handleOpen(openWithState)}
>
+ Add
</Button>
)
render () {
return (
<FormDialog
opener={this.opener}
/>
)
}
}
export default ScreenshotDialog
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment