form
Outputs an HTML <form> with the inputs the storefront needs to handle it. The form works without JavaScript: the storefront handles the post and redirects back, or to return_to.
{% form 'type', object, attribute: value %}
content
{% endform %}2
3
type: the form type, one of the types below. The quotes are optional.object: the object some types need, for example a product.attribute: value: any HTML attribute of the<form>tag, for exampleid,classordata-role. Values are escaped.return_to: where to go after a successful post. See Return to.
Every posted form also outputs a CSRF token, a form_type input and a hidden spam field. Do not remove them.
{% form 'contact', id: 'contact-form', class: 'contact' %}
<input type="email" name="email">
<button type="submit">Send</button>
{% endform %}2
3
4
<form method="post" action="https://store.youcan.store/contact" accept-charset="UTF-8" id="contact-form" class="contact">
<input type="hidden" name="form_type" value="contact">
<input type="hidden" name="_token" value="CSRF_TOKEN">
<input type="text" name="hidden_check" value="" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-9999px">
<input type="email" name="email">
<button type="submit">Send</button>
<div data-captcha>…</div>
</form>2
3
4
5
6
7
8
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 | The form type |
posted_successfully | 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 | The same submitted values, for example form.email |
form.errors has:
messages: the first message of each field, for exampleform.errors.messages.email.translated_fields: a readable name for each field, for exampleEmailforemail.- Looping over
form.errorsgives pairs:error[0]is the field,error[1]its messages.
The default_errors filter outputs all messages as a list:
{% form 'contact' %}
{% if form.posted_successfully %}
<p>{{ 'contact.success' | t }}</p>
{% endif %}
{{ form.errors | default_errors }}
<input type="email" name="email" value="{{ form.email }}">
{% endform %}2
3
4
5
6
7
<div class="errors"><ul><li>The email field is required.</li></ul></div>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.
{% form 'product', product, return_to: 'checkout' %}
<input type="number" name="quantity" value="1">
<button type="submit">{{ 'product.buy_now' | t }}</button>
{% endform %}2
3
4
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 |
{% form 'product', product %}
<input type="number" name="quantity" value="1" min="1">
<button type="submit">{{ 'product.add_to_cart' | t }}</button>
{% endform %}2
3
4
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 |
clear | no | Removes all items when present |
checkout | no | Goes to the checkout after the update when present |
{% form 'cart', cart %}
{% for item in cart.items %}
<input type="number" name="updates[{{ item.id }}]" value="{{ item.quantity }}" min="0">
{% endfor %}
<textarea name="note">{{ cart.note }}</textarea>
<button type="submit">{{ 'cart.update' | t }}</button>
<button type="submit" name="checkout">{{ 'cart.checkout' | t }}</button>
{% endform %}2
3
4
5
6
7
8
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. 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 |
{% form 'customer_login', return_to: routes.account_url %}
{{ form.errors | default_errors }}
<input type="email" name="email" value="{{ form.email }}">
<input type="password" name="password">
<button type="submit">Log in</button>
{% endform %}2
3
4
5
6
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 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 |
{% form 'customer_update' %}
{{ form.errors | default_errors }}
<input type="text" name="first_name" value="{{ customer.first_name }}">
<input type="text" name="last_name" value="{{ customer.last_name }}">
<input type="email" name="email" value="{{ customer.email }}">
<input type="password" name="current_password">
<button type="submit">Save</button>
{% endform %}2
3
4
5
6
7
8
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 |
{% for address in customer.addresses %}
{% form 'customer_address', address %}
<input type="text" name="first_line" value="{{ address.address1 }}">
<input type="text" name="city" value="{{ address.city }}">
<input type="text" name="country_code" value="{{ address.country_code }}">
<button type="submit">Save</button>
{% endform %}
{% endfor %}
{% form 'customer_address', customer.new_address %}
<input type="text" name="first_line">
<input type="text" name="city">
<input type="text" name="country_code">
<button type="submit">Add</button>
{% endform %}2
3
4
5
6
7
8
9
10
11
12
13
14
15
customer_address_remove
Removes an address. Pass the address as object. It needs no inputs.
{% form 'customer_address_remove', address %}
<button type="submit">Remove</button>
{% endform %}2
3