Skip to content

Demos#

Set data outside of the form#

const existingData = {
  foo: 'bar',
}
const Component = () => {
  const { data } = Form.useData('default-id', existingData)
  return (
    <Form.Handler id="default-id">
      <Field.String path="/foo" label={data.foo} />
    </Form.Handler>
  )
}
render(<Component />)

Update the data outside of the form#

The update function update('/count', (count) => count + 1) has TypeScript support and returns the correct type for count (number).

const existingData = {
  count: 1,
}
const Component = () => {
  const { data, update } = Form.useData('update-id', existingData)
  const increment = useCallback(() => {
    update('/count', (count) => {
      return count + 1
    })
  }, [update])
  return (
    <Form.Handler id="update-id">
      <Flex.Horizontal>
        <Field.Number path="/count" showStepControls />
        <Form.SubmitButton
          onClick={increment}
          text={`Increment ${data.count}`}
        />
      </Flex.Horizontal>
    </Form.Handler>
  )
}
render(<Component />)

Shared state without a Form.Handler#

const existingData = {
  count: 1,
}
const Component = () => {
  const { data, update } = Form.useData('independent-id', existingData)
  const increment = useCallback(() => {
    update('/count', (count) => {
      return count + 1
    })
  }, [update])
  return (
    <Button
      onClick={increment}
      text={`Increment ${data.count}`}
      variant="secondary"
    />
  )
}
render(
  <Flex.Vertical>
    <Component />
    <Component />
  </Flex.Vertical>
)

Get only data of visible fields#

You can use the reduceToVisibleFields function to get only the data of visible (mounted) fields.

const MyForm = () => {
  const { data, reduceToVisibleFields } = Form.useData()

  // Use useEffect to ensure we get the latest data
  useEffect(() => {
    console.log(
      'Result of reduceToVisibleFields:
',
      reduceToVisibleFields(data, {
        removePaths: ['/isVisible'],
      })
    )
  }, [data, reduceToVisibleFields])
  return (
    <Form.Handler>
      <Flex.Stack>
        <Field.Boolean
          label="Show radio buttons"
          variant="button"
          path="/isVisible"
          defaultValue={true}
        />

        <Form.Visibility pathTrue="/isVisible" animate>
          <Field.Selection
            label="Radio buttons"
            variant="radio"
            path="/myValue"
            defaultValue="foo"
          >
            <Field.Option value="foo" title="Foo" />
            <Field.Option value="bar" title="Bar" />
          </Field.Selection>
        </Form.Visibility>

        <Value.Selection path="/myValue" inheritLabel inheritVisibility />
      </Flex.Stack>
    </Form.Handler>
  )
}
render(<MyForm />)
SyntaxError: Invalid or unexpected token

Filter your data#

This example uses the keepInDOM property to keep the field in the DOM.

But with the filterData method we can filter out all fields that have the data-exclude-field attribute.

In this demo, the data-exclude-field attribute is added when the field is hidden.

Filtered:
{} 
All data:
{
  "isVisible": false,
  "mySelection": "less",
  "myString": "foo"
} 
const filterDataPaths = {
  '/isVisible': false,
  '/mySelection': ({ data }) => data.isVisible,
  '/myString': ({ data }) => {
    return data.isVisible && data.mySelection === 'more'
  },
}
const MyForm = () => {
  return (
    <Form.Handler
      defaultData={{
        isVisible: false,
        mySelection: 'less',
        myString: 'foo',
      }}
    >
      <Flex.Stack>
        <Field.Boolean
          label="Toggle visible"
          variant="button"
          path="/isVisible"
          data-exclude-field
        />
        <Form.Visibility pathTrue="/isVisible" animate>
          <Field.Selection
            label="Choose"
            variant="radio"
            path="/mySelection"
            value="less"
          >
            <Field.Option value="less" title="Less" />
            <Field.Option value="more" title="More" />
          </Field.Selection>

          <Form.Visibility
            visibleWhen={{
              path: '/mySelection',
              hasValue: 'more',
            }}
            animate
          >
            <Field.String label="My String" path="/myString" value="foo" />
          </Form.Visibility>
        </Form.Visibility>

        <Output />
      </Flex.Stack>
    </Form.Handler>
  )
}
const Output = () => {
  const { data, filterData } = Form.useData()
  return (
    <>
      <Tools.Log data={filterData(filterDataPaths)} label="Filtered:" />
      <Tools.Log data={data} label="All data:" />
    </>
  )
}
render(<MyForm />)
Suggest an edit