Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/forms / src / new-forms / forms / ObserverForm.tsx
Size: Mime:
import * as React from 'react'
import { observer } from 'xmobx/mobx-react'
import { FormEvent } from 'react'
import { isFunction } from 'exotic'
import { ValidationStrategyContext, ValidationStrategy } from '../strategies'
import { defaultRenderForm, defaultRenderButtonGroup } from './renderProps'
import { FormProps, FormRenderProps } from './typings'
import { Provider } from './FormContext'

@observer
export class ObserverForm extends React.Component<FormProps> {
  static defaultProps = {
    renderForm: defaultRenderForm,
    renderButtonGroup: defaultRenderButtonGroup,
  }
  static contextType = ValidationStrategyContext
  context: ValidationStrategy

  handleSubmit = (event: FormEvent<any>) => {
    event.preventDefault()

    /**
     * this is also where we can focus
     * all the errored inputs
     *
     * we can also update the state here that is used by the button
     * for example, adding a property such as
     *  "isSubmitting"
     *  "didSubmitSuccessfully"
     *  "didSubmitError"
     */

    const { state } = this.props
    const onSubmit = this.props.onSubmit || this.context.onSubmit
    if (isFunction(onSubmit)) {
      onSubmit({ state, event })
    } else {
      // @todo if not production @@production
      const serialized = state.toJSON()
      console.warn('[1forms] no onSubmit prop used')
      console.log(serialized)
    }
  }

  render() {
    const {
      renderForm,
      renderButtonGroup,
      renderInput,
      ...remainingProps
    } = this.props

    // @note - not destructuring above so it stays in `remainingProps`
    const inputListView = this.props.state.inputsList.map(renderInput)

    const baseAttributes = {
      ...remainingProps,
      onSubmit: this.handleSubmit,
    } as FormRenderProps

    // @todo - get name from schema.org?
    const submitView = renderButtonGroup(baseAttributes)

    // @invariant - submit button always comes after form
    //              anyone asking you to change this is bad ux
    const children = (
      <React.Fragment>
        {inputListView}
        {submitView}
      </React.Fragment>
    )

    const attributes = {
      ...baseAttributes,
      id: this.props.state.identifier,
      children,
    }

    const formView = renderForm(attributes)

    return <Provider value={this.props.state}>{formView}</Provider>
  }
}