You can create HTML forms in B2C Commerce using templates and controllers. Using form definitions, you can also persist form data during a session and store it in system objects or custom objects.
You can create a standard HTML form that uses AJAX for validation and error rendering. If you're creating a simple form that doesn't store data, is easily localized, and only requires client-side validation, this type of form is appropriate. You can also create a complex form that stores data, requires server-side validation, and has sophisticated localization requirements. Sophisticated localization can include adding, removing, or rearranging fields in the form or changing the data object you have to store with form data.
If you're creating a complex form, use a B2C Commerce form definition. A form definition results in an in-memory object that persists during the session. You can use this object with various platform features for localization, server-side validation, and data storage.
The following example uses a form definition. The form has a text field to input a nickname, a submit button, and a cancel button. After the form is submitted, another page is rendered that shows the nickname entered in the previous form.
The first thing you create for a form is the form definition. The form definition describes the data you need from the form, the data validation, and the system objects you want to store the data in. This example only has one input field and two buttons. This form doesn't validate or store data permanently.
The form definition determines the structure of the in-memory form object. The in-memory form object persists data during the session, unless you explicitly clear the data.
In the Storefront Reference Architecture (SFRA), the first step to create a form is to create a JSON object to contain the form data. The
server.getForm function uses the form definition to create this object. Data from the form is accessible in templates using the
pdict variable. However, the form is available only if the
server.getForm object is passed to the template by the controller.
The controller in this example exposes a
Start function that renders an empty form.
Start function sets the
actionURL that's used to handle the submit action for the form and creates a JSON object based on the form definition.
In this example,
SFRAFormTemplate.isml is the empty form rendered for the user and the
SFRAResultTemplate.isml shows data entered into the form.
The form action uses the
actionUrl property passed to it by the controller.
After a form is submitted, data from the form is available as part of the
req.form property. In the following example, the nickname entered in the original form is passed to a new template for rendering.
This template prints the form field label and data stored from the form.
Most SFRA forms are standard HTML forms, so you can use
input type="hidden" to hide form fields in templates.
The form you create in your template can contain fields from multiple form definitions. The same fields can be reused in other forms as many times as required. This ability can be useful for prepopulating form data that the customer has already entered. For example, address or payment preference data.
You can use the metadata entered for a custom or system object in Business Manager to determine form definition information. This ability lets you manage data attributes in one place without having to change code. For example, if you wanted to let merchants change the labels on form fields, you could include
label as a metadata attribute and reference it.
SFRA doesn't include dynamic forms.
However, if you want to create them, you can use the
isdynamicform tag to generate dynamic forms. The
dynamicform.isml template and the
dynamicForm.js script control how code is generated using the
SFRA doesn't include multi-part, embedded, or nested forms. We don't recommend them as a best practice.
You can change the structure of a form depending on the locale. For example, you can include different address fields, such as state or province, depending on the country. To localize the form structure, you can create different form definitions for each locale. These form definitions have the same name, but a different structure or different fields for different locales.
In your cartridge, create a
forms/default folder for the standard locale and then separate folders that are named for each locale of the form. Store a different form definition in each locale folder. If a locale doesn't have a separate folder, the default form definition is used.
You can use resource strings directly from a form. The following example is of the
loginform.isml that logs customers into the site. In this case, the form uses the
label.input.login.email resource string identifier.
Depending on the locale, this resource identifier resolves to different values
In the English
In the French
Remember to add the country to select to your country selector and to configure the locale for the site in Business Manager.
All form strings can be replaced with resource strings. Resource strings for forms are located by default in the
forms.properties file for your cartridge and referenced from the form definition file. Add files with the name
forms_locale_.properties to add localized strings. For example, add a
forms_it_IT.properties file for an Italian version of the same properties. You can have different fields for the form, depending on the locale. Make sure that the strings for those fields are included in the localized version of the properties files.
The following form definition file defines a form to enter contact information. This example doesn't show the entire form definition, just some of the fields that use localized strings for labels and error messages. You can find this file as the
contactus.xml form in the SiteGenesis
The label and error strings in bold reference the properties set in the
forms.properties file, which contains entries like the following for the default site locale:
The form is localized in the
forms_it_IT.properties file (along with the other locale-specific
forms_locale_.properties files) with entries like the following:
Server-side validation on form data is configured in the form definition. SFRA uses jQuery AJAX methods to render a page after server-side validation.
The attributes set on the form field are used for validation. In the following example, the
mandatory attribute requires a value for the field. The
regexp attribute determines the content of the field. And the
max-length attribute sets the maximum length of the data for the field.
max-length attribute is used only for validation of strings. For other field types, it's used only to format the field length and not to validate data.
Errors shown for attribute validation:
Default error for form invalidation:
Mandatory flag invalid:
Entered value invalid:
You can also use the validation attribute to specify a function to run to validate form data. You can run these validations on container elements, such as form or group, or on individual fields.
You can also selectively invalidate form elements using the
InvalidateFormElement pipelet in pipelines or the
invalidateFormElement function in the
FormModel or any model that requires it. If any element in a form is invalid, the entire form is invalid. However, in your form definition, you can create error messages that are specific to a field. See the example of
range-error, which points to a resource string with a message for the customer on why the field is invalid.
B2C Commerce provides two utility scripts you can use for validating form data:
document.ready. This file is located in
- client-side-validation: This script validates the entire form and clears a form for validation. This file is required by
main.js. It’s located in
route:BeforeComplete event is used to store form data. Different APIs are used to save data, depending on the type of form.
This example constructs an object that contains the relevant information from the form and saves it to the
ViewData object, so it can be passed. This example can be seen in the
In SFRA, you use the
server.getForms function to get the form data structure from the relevant form definition and convert it into a JSON object. The object is then added to the data passed to the template, so that it's available to the template via the
pdict variable. To clear the form, you must manually call the
This example gets the profile form and clears it.
You can prepopulate forms with information from system objects, custom objects, and form data.
You can use the
server module ``form.js
You can use the
copyFrom function to get data from an existing form object. Usually, if you have used
app.getForm to get a copy of a form model, it makes more sense to use the function. You can also transfer form data from one form to another directly. In the following example, if a customer decides to use the shipping address for billing, the values from one form are copied to the other.
To copy values from one custom object to another, don't use the
copyTo() methods. The
You can prepopulate forms with information from system objects, custom objects, and in-memory form data. This data is available directly from the model you're working with or from the
ViewData object used for rendering the template. The
server module in the
modules folder includes a
forms.js module that converts form data into JSON objects. For more information, see the following functions in the server-side JSDoc.
SFRA provides a forms module that abstracts the form definition into a JSON representation. If you want to work with JSON objects, use the modules and forms methods to get and store data.
Use the new CSRF (Cross-Site Request Forgery) framework to add fields that are protected from request forgery.
CSRF in SFRA is provided as middleware by B2C Commerce. CSRF checks are performed as the middleware step
Example: CSRF check is made for login information. This example is available in the
For more information, see
validateAjaxRequest in the JSDoc.