);
}
export async function action({request, context}: ActionArgs) {
const cart = context.cart as HydrogenCart;
// cart is type HydrogenCart or HydrogenCartCustom
// Declare cart type in remix.env.d.ts for interface AppLoadContext to avoid type casting
// const {cart} = context;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let status = 200;
let result: CartQueryData;
if (action === CartForm.ACTIONS.MetafieldsSet) {
result = await cart.setMetafields(inputs.metafields);
} else {
invariant(false, `${action} cart action is not defined`);
}
const headers = cart.setCartId(result.cart.id);
return json(result, {status, headers});
}
```
## Examples
Creates a form for managing cart operations. Use `CartActionInput` to accept form inputs of known type.
### CartForm using HTML input tags as form inputs
Use HTML input tags with CartForm to accept form inputs.```jsx
import {json} from '@remix-run/server-runtime';
import {CartForm} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';
export default function Note() {
return (
);
}
export async function action({request, context}) {
const cart = context.cart;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let status = 200;
let result;
if (action === CartForm.ACTIONS.NoteUpdate) {
result = await cart.updateNote(inputs.note);
} else {
invariant(false, `${action} cart action is not defined`);
}
const headers = cart.setCartId(result.cart.id);
return json(result, {status, headers});
}
```
```tsx
import {type ActionArgs, json} from '@remix-run/server-runtime';
import {
type CartQueryData,
type HydrogenCart,
CartForm,
} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';
export default function Note() {
return (
);
}
export async function action({request, context}: ActionArgs) {
const cart = context.cart as HydrogenCart;
// cart is type HydrogenCart or HydrogenCartCustom
// Declare cart type in remix.env.d.ts for interface AppLoadContext to avoid type casting
// const {cart} = context;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let status = 200;
let result: CartQueryData;
if (action === CartForm.ACTIONS.NoteUpdate) {
result = await cart.updateNote(inputs.note);
} else {
invariant(false, `${action} cart action is not defined`);
}
const headers = cart.setCartId(result.cart.id);
return json(result, {status, headers});
}
```
### Custom actions
Create custom actions to accept form inputs of unknown type. Just prepend `Custom` in front of your custom action name.```jsx
import {json} from '@remix-run/server-runtime';
import {CartForm} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';
export default function Cart() {
return (
);
}
export async function action({request, context}) {
const {cart} = context;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let status = 200;
let result;
if (action === 'CustomEditInPlace') {
result = await cart.addLines(inputs.addLines);
result = await cart.removeLines(inputs.removeLines);
} else {
invariant(false, `${action} cart action is not defined`);
}
const headers = cart.setCartId(result.cart.id);
return json(result, {status, headers});
}
```
```tsx
import {type ActionArgs, json} from '@remix-run/server-runtime';
import {
type CartQueryData,
type HydrogenCart,
CartForm,
} from '@shopify/hydrogen';
import {type CartLineInput} from '@shopify/hydrogen-react/storefront-api-types';
import invariant from 'tiny-invariant';
export default function Cart() {
return (
);
}
export async function action({request, context}: ActionArgs) {
const cart = context.cart as HydrogenCart;
// cart is type HydrogenCart or HydrogenCartCustom
// Declare cart type in remix.env.d.ts for interface AppLoadContext to avoid type casting
// const {cart} = context;
const formData = await request.formData();
const {action, inputs} = CartForm.getFormInput(formData);
let status = 200;
let result: CartQueryData;
if (action === 'CustomEditInPlace') {
result = await cart.addLines(inputs.addLines as CartLineInput[]);
result = await cart.removeLines(inputs.removeLines as string[]);
} else {
invariant(false, `${action} cart action is not defined`);
}
const headers = cart.setCartId(result.cart.id);
return json(result, {status, headers});
}
```
### CartForm with fetcher
Use `CartForm` with a fetcher to manually submit the form. An example usage is to submit the form on changes to the state of a checkbox.
When using fetcher to submit, make sure to have a `CartForm.INPUT_NAME` data key and its data should be a JSON stringify object.```jsx
import {useFetcher} from '@remix-run/react';
import {json} from '@remix-run/server-runtime';
import {CartForm} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';
export function ThisIsGift({metafield}) {
const fetcher = useFetcher();
const buildFormInput = (event) => ({
action: CartForm.ACTIONS.MetafieldsSet,
inputs: {
metafields: [
{
key: 'custom.gift',
type: 'boolean',
value: event.target.checked.toString(),
},
],
},
});
return (