---
schema_version: "1"
id: e1633d72540b49047282e9bd956817ea06aebb01195977ef7d6237355c75eebe
title: Forms
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/b2c-commerce/guides/sfra/b2c-forms.md
canonical_url: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/b2c-forms.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: e69018a2d8dbe96094418698d9a0dc73ecef7a45e80c7425b278e70cfc3b0fe3
products:
  - Composable Storefront
  - Salesforce APIs
---
# Forms

Create HTML forms in B2C Commerce using templates and controllers. Using form definitions, persist form data during a session and store it in system objects or custom objects.

## Creating a Form

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. 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. 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.

### Form Definition

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.

SFRAFormDef.xml

```
<?xml version="1.0"?>
<form xmlns="http://www.demandware.com/xml/form/2008-04-19">
	<field formid="nickname" label="Nickname:" type="string" mandatory="true" max-length="50" />
	<action formid="submit" valid-form="true"/>
	<action formid="cancel" valid-form="false"/>
</form>
```

### In-memory Form Object

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.

### Controller to Render the Form

The controller in this example exposes a `Start` function that renders an empty form.

The `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.

#### SFRAForm.Js

```
/**
 * A simple form controller.
 *
 */

'use strict';
var server = require('server');
var URLUtils = require('dw/web/URLUtils');

server.get(
 'Start', server.middleware.http, function (req, res, next) {
    var actionUrl = URLUtils.url('SFRAFormResult-Show'); //sets the route to call for the form submit action
 var SFRAhelloform = server.forms.getForm('SFRAFormDef'); //creates empty JSON object using the form definition
 SFRAhelloform.clear();

   res.render('SFRAFormTemplate', {
       actionUrl: actionUrl,
       SFRAhelloform: SFRAhelloform
   });
 next();
});

module.exports = server.exports();
```

### Form Template - SFRAFormTemplate.isml

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.

The client-side JavaScript and css files are included using the `assets.j`s module.

```
<!--- TEMPLATENAME: helloform.isml --->
 <!--- <isscript>
var assets = require('*/cartridge/scripts/assets.js');
assets.addCss('/css/helloform.css');
assets.addJs('/js/helloform.js'); </isscript>--->

<div class="hero slant-down login-banner">
	<h1>SFRA Hello World Form</h1>
</div>

<!--- --->
<div class="card">
	<form action="${pdict.actionUrl}" class="login" method="POST"
		name="SFRAHelloForm">

		<div class="form-group required">
			<label> Nickname: </label> <input type="input" id="nickname"
				class="form-control" name="nickname">
		</div>

		<button type="submit" class="btn btn-block btn-primary">Submit</button>
		<button type="submit" class="btn btn-block btn-primary">Cancel</button>
	</form>
</div>
```

### Controller to Render Form Results - SFRAFormResult.Js

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.

```
/**
 * Handles the simple form rendered by the SFRAForm.js controller.
 *
 */

'use strict';
var server = require('server');
var URLUtils = require('dw/web/URLUtils');


server.post('Show', server.middleware.http,
  function(req, res, next) {

  var nickname = req.form.nickname;

  res.render('SFRAResultTemplate', {
    nickname : nickname});
   next();
  });

module.exports = server.exports();
```

### Form Result Template - SFRAResultTemplate.isml

This template prints the form field label and data stored from the form.

```
<<!--- TEMPLATENAME: SFRAResultTemplate.isml --->
<iscontent type="text/html" charset="UTF-8" compact="true" />
<!doctype html>
<head></head>
<body>
<h1>Hello World Form Result</h1>
<p>Nice to meet you, ${pdict.nickname}.</p>
</body>
</html>
```

### Hiding Form Fields

Most SFRA forms are standard HTML forms, so use `input type="hidden"` to hide form fields in templates.

### Reusing Form Definitions

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.

### Using Form Metadata

Use the metadata entered for a custom or system object in Business Manager to determine form definition information. This manages 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.

### Dynamic, Multi-Part, Embedded, or Nested Forms

SFRA doesn't include dynamic forms.

However, if you want to create them, use the `isdynamicform` tag to generate dynamic forms. The `dynamicform.isml` template and the `dynamicForm.js` script control how code is generated using the `isdynamicform` tag.

SFRA doesn't include multi-part, embedded, or nested forms. We don't recommend them as a best practice.

## Localizing a Form

Change the structure of a form depending on the locale. For example, include different address fields, such as state or province, depending on the country. To localize the form structure, 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.

```
forms
	default
		billingaddress.xml
	it_IT
		billingaddress.xml
	ja_JP
	billingaddress.xml
```

### Localizing Strings Within Simple Forms

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.`

```
<form action="${pdict.actionUrl}" class="login" method="POST" name="login-form">
    <div class="form-group required">
        <label class="form-control-label" for="login-form-email">
            ${Resource.msg('label.input.login.email', 'login', null)}
        </label>
        <input type="email" id="login-form-email" class="form-control" name="loginEmail" value="${pdict.userName}">
        <div class="form-control-feedback"></div>
    </div>
```

Depending on the locale, this resource identifier resolves to different values

In the English `app_storefront_base/cartridge/templates/resources/login.properties` file:

```
label.input.login.email=Email
```

In the French `app_storefront_base/cartridge/templates/resources/login_fr_FR.properties` file:

```
label.input.login.email=E-mail
```

**note:** Remember to add the country to select to your country selector and to configure the locale for the site in Business Manager.

### Localizing Strings Within Complex Forms

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. Different fields for the form may be needed, depending on the locale. Make sure that the strings for those fields are included in the localized version of the properties files.

### Example: Localizing Labels and Error Messages

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. Find this file as the `contactus.xml` form in the SiteGenesis `app_storefront_core` cartridge.

```
<?xml version="1.0"?>
<form xmlns="http://www.demandware.com/xml/form/2008-04-19">

	<field formid="firstname" label="contactus.firstname.label" type="string" mandatory="true" binding="firstName" max-length="50"/>
	<field formid="lastname" label="contactus.lastname.label" type="string" mandatory="true" binding="lastName" max-length="50"/>
	<field formid="email" label="contactus.email.label" type="string" mandatory="true"  parse-error="contactus.email.parse-error" />
```

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:

```
##############################################
# Template name: forms/contactus
##############################################
contactus.firstname.label=First Name
contactus.lastname.label=Last Name
contactus.email.label=Email
contactus.email.parse-error=The email address is invalid.
```

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:

```
##############################################
# Template name: forms/contactus
##############################################
contactus.firstname.label=Nome
contactus.lastname.label=Cognome
contactus.email.label=Email
contactus.email.parse-error=L'indirizzo email non Ã¨ valido.
```

## Validating Form Data

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.

### Validation by Attribute

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.

**note:** The `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.

```
<field formid="email" label="contactus.email.label" type="string" mandatory="true" regexp="^[\w.%+-]+@[\w.-]+\.[\w]{2,6}$" max-length="50"/>
```

Errors shown for attribute validation:

- Default error for form invalidation: `value-error`
- Mandatory flag invalid: `missing-error`

- Entered value invalid: `parse-error`

### Validation by Function

Use the validation attribute to specify a function to run to validate form data. Run these validations on container elements, such as form or group, or on individual fields.

```
<field formid="password"
       label="label.password"
       type="string"
       range-error="resource.customerpassword"
       validation="${require('~/cartridge/scripts/forms/my_custom_script.ds').my_custom_validation(formfield);}"
```

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, 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.

### Client-Side Validation Scripts

Simple forms are standard HTML forms, so use any client-side validation method you choose. B2C Commerce uses default HTML5 validation for client-side validation. Find the client-side JavaScript for a page by identifying the script added by the `assets.AddJs` function.

B2C Commerce provides two utility scripts for validating form data:

- form-validation: This script validates a specific field in the form. It uses the validation criteria set in the form definition and included in the attributes for the form JSON object. This script is required by the client-side JavaScript doing the validation for a specific form and is loaded at `document.ready`. This file is located in `app_storefront_base/cartridge/client/js/default/components/form-validation.js`.
- 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 `app_storefront_base/cartridge/client/js/default/components/client-side-validation.js`

## Saving Form Data

The `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 `Account.js` `SavePassword` function.

```
var profileForm = server.forms.getForm('profile');       //gets the profile form object
var newPasswords = profileForm.login.newpasswords;
...
var result = {                                           //constructs an object containing the form result
    currentPassword: profileForm.login.currentpassword.value,
    newPassword: newPasswords.newpassword.value,
    newPasswordConfirm: newPasswords.newpasswordconfirm.value,
    profileForm: profileForm
};

if (profileForm.valid) {
    res.setViewData(result);                         // adds form result to the ViewData object
    this.on('route:BeforeComplete', function () { // creates the function to run before middleware completion
        var formInfo = res.getViewData();            // creates object with data to save
        var customer = CustomerMgr.getCustomerByCustomerNumber( //gets current customer
            req.currentCustomer.profile.customerNo
        );
        var status;
        Transaction.wrap(function () {                //saves the new customer password and returns status
            status = customer.profile.credentials.setPassword(
                formInfo.newPassword,
                formInfo.currentPassword,
                true
            );
        });
```

## Clearing or Refreshing a Form

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 `clear` method.

This example gets the profile form and clears it.

```
function (req, res, next) {
    var accountModel = getModel(req);
    var profileForm = server.forms.getForm('profile'); //gets the profile form object
    profileForm.clear();              //clears the form using a function from the server module forms.js
```

## Prepopulating Form Data

Prepopulate forms with information from system objects, custom objects, and form data.

### To Get Data from System Objects

Use the `server` module `form.js`copyObjectToForm` method to get data from an existing form object. Use the metadata attributes for a system or custom object to prefill form data.

### To Get Data from Other Forms

Use the `FormModel`.js `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. 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.

```
server.get(
    'EditProfile',
    server.middleware.https,
    csrfProtection.generateToken,
    userLoggedIn.validateLoggedIn,
    function (req, res, next) {
        var accountModel = getModel(req);
        var profileForm = server.forms.getForm('profile'); //gets the profile.xml form definition and converts it to a JSON object.
        profileForm.clear();                               //clears the JSON object
        profileForm.customer.firstname.value = accountModel.profile.firstName;    //copies data from one field to another
        profileForm.customer.lastname.value = accountModel.profile.lastName;
        profileForm.customer.phone.value = accountModel.profile.phone;
        profileForm.customer.email.value = accountModel.profile.email;
        res.render('account/profile', {
            profileForm: profileForm,                                          //adds the JSON object to the data for the template
            breadcrumbs: [
                {
                    htmlValue: Resource.msg('global.home', 'common', null),
                    url: URLUtils.home().toString()
                },
                {
                    htmlValue: Resource.msg('page.title.myaccount', 'account', null),
                    url: URLUtils.url('Account-Show').toString()
                }
            ]
        });
        next();
    }
    );
```

### To Copy Values from One Object to Another

To copy values from one custom object to another, don't use the `dw.web.FormGroup` `copyFrom()` and `copyTo()` methods. The `copyTo()` method requires a form submit to set values in the custom object. Instead, use Javascript to directly copy the values, as in this example:

```
let testObject = { name:"default name", subject:"default subject", message:"default message" };
let output = {};
Object.keys( testObject ).forEach( function( key ) {
   output[key] = testObject[key];
});
```

## Converting Form Data to JSON Objects

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.

- `parseForm(Form)`
- `copyObjectToForm(object, CurrentForm)`
- `findValue(formGroup, name)`
- `clearOptions(obj)`

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.

## Securing Forms

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 `csrfProtection.validateAjaxRequest.`

Example: CSRF check is made for login information. This example is available in the `Account.js` controller.

```
server.post(
    'Login',
    server.middleware.https,
    csrfProtection.validateAjaxRequest,
    function (req, res, next) {
        var data = res.getViewData();
        if (data && data.csrfError) {
            res.json();
            return next();
        }
```

For more information, see `validateRequest` and `validateAjaxRequest` in the JSDoc.
