---
url: https://docs.youcan.shop/themes/tags/form.md
---
# `form`
Outputs an HTML `
```
## The `form` object
Inside a form, `form` describes the last post of that form type. It is empty on a normal page view.
| Name | Type | Description |
| --------------------- | ------------------------------------------ | ----------------------------------------------------------------- |
| `type` | [string](../basics/types#string) | The form type |
| `posted_successfully` | [boolean](../basics/types#boolean) | Whether this form was posted and the post succeeded |
| `errors` | form errors | The errors of the post, or nil |
| `values` | object | The submitted values when the post failed, without passwords |
| any field name | [string](../basics/types#string) | The same submitted values, for example `form.email` |
`form.errors` has:
* `messages`: the first message of each field, for example `form.errors.messages.email`.
* `translated_fields`: a readable name for each field, for example `Email` for `email`.
* Looping over `form.errors` gives pairs: `error[0]` is the field, `error[1]` its messages.
The `default_errors` filter outputs all messages as a list:
```liquid
{% form 'contact' %}
{% if form.posted_successfully %}
```
## Return to
`return_to` sets where to go after a successful post. A failed post always goes back to the page of the form, so the errors can show.
* A path on the store, for example `/cart`.
* `back`: the page the form was on.
* `checkout`: the checkout, one page or step by step, depending on the cart.
Other values, including URLs on other domains, are ignored.
```liquid
{% form 'product', product, return_to: 'checkout' %}
{% endform %}
```
## Types
### `product`
Adds a product to the cart. With a product as `object`, the form outputs the `id` input of the selected or first available variant. A product with "skip to checkout" goes to the checkout after the post, unless you set `return_to`.
| Input | Required | Description |
| ---------------- | -------- | ------------------------------------------------------ |
| `id` | yes | The variant id. Output for you when you pass a product |
| `quantity` | yes | The quantity |
| `attachedImage` | no | The URL of an image the customer uploaded, for variants that need one |
```liquid
{% form 'product', product %}
{% endform %}
```
A `select` named `id` inside the form replaces the variant the form outputs.
### `express_checkout`
Places an order from the product page in one step. Pass the product as `object`. After the post the customer goes to the thank you page, to the upsell offers, or to the shipping or payment step when the store needs them. `return_to` is not used.
| Input | Required | Description |
| -------------------------------------------- | -------------------- | ------------------------------ |
| `quantity` | yes | The quantity |
| checkout fields, for example `first_name` and `phone` | as set by the store | The customer details |
Field errors come back in `form.errors`.
### `cart`
Updates the cart.
| Input | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------ |
| `updates[ITEM_ID]` | no | The new quantity of a cart item. `0` removes it |
| `note` | no | The cart note. Read it with [`cart.note`](../objects/cart) |
| `clear` | no | Removes all items when present |
| `checkout` | no | Goes to the checkout after the update when present |
```liquid
{% form 'cart', cart %}
{% for item in cart.items %}
{% endfor %}
{% endform %}
```
### `coupon`
Applies a coupon to the cart.
| Input | Required | Description |
| -------- | -------- | --------------- |
| `coupon` | yes | The coupon code |
### `coupon_remove`
Removes the coupon from the cart. It needs no inputs.
### `product_review`
Adds a review to a product. Pass the product as `object`. Reviews wait for the seller's approval.
| Input | Required | Description |
| ------------ | -------- | --------------------------------- |
| `ratings` | yes | A rating from 0 to 5 |
| `content` | no | The review text, 5 to 2000 characters |
| `first_name` | no | The reviewer's first name |
| `last_name` | no | The reviewer's last name |
| `email` | no | The reviewer's email |
| `images[]` | no | Image URLs |
### `contact`
Sends a message to the seller. The form outputs a captcha.
| Input | Required | Description |
| --------- | -------- | ---------------------- |
| `email` | yes | The customer's email |
| `subject` | yes | The subject |
| `message` | yes | The message |
## Customer types
These types handle customer accounts. Use them in the [customer templates](/themes/templates/overview#template-types). The `customer_login`, `create_customer`, `recover_customer_password`, `reset_customer_password` and `customer` forms output a captcha, and the post fails without it.
### `customer_login`
Logs the customer in. After the post the customer goes to `return_to`, or to the home page.
| Input | Required | Description |
| ---------- | -------- | ------------------------------------------- |
| `email` | yes | The customer's email |
| `password` | yes | The password |
| `remember` | no | Keeps the customer logged in when checked |
```liquid
{% form 'customer_login', return_to: routes.account_url %}
{{ form.errors | default_errors }}
{% endform %}
```
### `create_customer`
Creates an account. After the post the customer goes to the login page. When the email belongs to a past customer without an account, the store sends an email to set the password.
| Input | Required | Description |
| ----------------------- | -------- | ----------------------------------- |
| `email` | yes | The customer's email |
| `password` | yes | The password, 6 to 72 characters |
| `password_confirmation` | yes | The same password |
| `first_name` | no | The first name |
| `last_name` | no | The last name |
| `phone` | no | The phone number |
### `recover_customer_password`
Sends a password reset email. The store sends it only when an account exists for the email, and the post succeeds in both cases.
| Input | Required | Description |
| ------- | -------- | -------------------- |
| `email` | yes | The customer's email |
### `reset_customer_password`
Sets a new password from the link in the reset email. Use it in the [`customer-reset-password`](/themes/templates/template-types/customer-reset-password) template. The form takes the reset link from the page URL. After the post the customer is logged in and goes to the home page.
| Input | Required | Description |
| ----------------------- | -------- | ----------------------------------- |
| `password` | yes | The new password, 6 to 72 characters |
| `password_confirmation` | yes | The same password |
### `customer_update`
Updates the logged in customer.
| Input | Required | Description |
| ----------------------- | ----------------------------------------- | ----------------------------------- |
| `first_name` | yes | The first name, 2 or more characters |
| `last_name` | yes | The last name, 2 or more characters |
| `email` | yes | The email |
| `phone` | no | The phone number |
| `password` | no | A new password, 6 to 72 characters |
| `password_confirmation` | with `password` | The same password |
| `current_password` | when the email or the password changes | The current password |
```liquid
{% form 'customer_update' %}
{{ form.errors | default_errors }}
{% endform %}
```
### `customer`
Subscribes an email to the store's marketing emails. The customer does not need an account.
| Input | Required | Description |
| ------- | -------- | ----------- |
| `email` | yes | The email |
### `customer_address`
Adds or updates an address of the logged in customer. Pass `customer.new_address` as `object` to add an address. Pass an address from `customer.addresses` to update it: the form outputs its `id` input. A customer can save up to 50 addresses.
| Input | Required | Description |
| -------------- | -------- | ------------------------------------------------ |
| `first_line` | yes | The first address line |
| `city` | yes | The city |
| `country_code` | yes | The country code, for example `MA` |
| `first_name` | no | The first name |
| `last_name` | no | The last name |
| `company` | no | The company |
| `second_line` | no | The second address line |
| `region` | no | The region |
| `zip_code` | no | The zip code |
| `phone` | no | The phone number |
| `default` | no | `1` makes it the default address |
```liquid
{% for address in customer.addresses %}
{% form 'customer_address', address %}
{% endform %}
{% endfor %}
{% form 'customer_address', customer.new_address %}
{% endform %}
```
### `customer_address_remove`
Removes an address. Pass the address as `object`. It needs no inputs.
```liquid
{% form 'customer_address_remove', address %}
{% endform %}
```