Skip to content

Commit

Permalink
[Docs] Add a guide on how to use a block in a Final Form (#2619)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnyomair authored Oct 16, 2024
1 parent 73c07ea commit 8f23414
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 2 deletions.
124 changes: 124 additions & 0 deletions docs/docs/blocks/blocks-in-forms.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
title: Blocks in forms
sidebar_position: 6
---

# Using blocks in forms

This guide describes how to use a block in a Final Form.
We use a product form with a `DamImageBlock` as an example.
The product has the following schema in GraphQL:

```graphql
type Product {
id: ID!
title: String!
// highlight-next-line
image: DamImageBlockData!
}
```

The following steps are necessary to add the `image` field to the form:

1. Create a Final Form component for the block
2. Create the block state when initializing the form
3. Create the block output when submitting the form

:::info

The block transitions between the various states when being used in a form.
The states and transitions can be viewed [here](/docs/blocks/lifecycle#the-block-in-the-admin).

:::

## Create a Final Form component for the block

The block's `AdminComponent` API (`state`, `updateState`) must be converted to the `Field` API (`input.value`, `input.onChange`).
Use the [createFinalFormBlock](https://github.com/vivid-planet/comet/blob/main/packages/admin/blocks-admin/src/form/createFinalFormBlock.tsx) helper for this:

```tsx
import { createFinalFormBlock } from "@comet/blocks-admin";

const FinalFormDamImageBlock = createFinalFormBlock(DamImageBlock);
```

Use the newly created component in the corresponding `Field` via the `component` prop:

```tsx
import isEqual from "lodash.isequal";

<Field
name="image"
isEqual={isEqual}
// highlight-next-line
component={FinalFormDamImageBlock}
/>;
```

:::note

A deep equality check using `isEqual` is necessary because the block state is an object.

:::

## Create the block state when initializing the form

The block state needs to be created when initializing the form.
If a product exists (i.e., in edit mode), transform the block input to the block state.
When creating a new product, use the block's default values:

```tsx
import { BlockState } from "@comet/blocks-admin";
import isEqual from "lodash.isequal";

type FormValues = Omit<GQLProductFormFragment, "image"> & {
// highlight-next-line
image: BlockState<typeof DamImageBlock>;
};

const { data } = useQuery(productFormQuery, id ? { variables: { id } } : { skip: true });

const initialValues = useMemo<Partial<FormValues>>(
() =>
data?.product
? {
...filterByFragment<GQLProductFormFragment>(productFormFragment, data.product),
// highlight-next-line
image: DamImageBlock.input2State(data.product.image),
}
: {
inStock: false,
// highlight-next-line
image: DamImageBlock.defaultValues(),
},
[data],
);

<FinalForm
// highlight-next-line
initialValues={initialValues}
initialValuesEqual={isEqual}
/>;
```

:::note

A deep equality check using `initialValuesEqual` is necessary when using blocks in a form.

:::

## Create the block output when submitting the form

Transform the block state to the block output before submitting the form:

```tsx
const handleSubmit = async (values: FormValues) => {
const input = {
...values,
// highlight-next-line
image: DamImageBlock.state2Output(values.image),
};

/* Create or update the product... */
};
```
2 changes: 1 addition & 1 deletion docs/docs/blocks/composition.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Composition
sidebar_position: 4
sidebar_position: 5
---

# Composing blocks
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/blocks/lifecycle.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Lifecycle
sidebar_position: 5
sidebar_position: 7
---

# Deep dive: A block's lifecycle
Expand Down

0 comments on commit 8f23414

Please sign in to comment.