Forms and Validations

By Nikola Gorjanac


Forms and validations are playing a big role in any project. We want to prevent invalid data inputs and teach users to enter data that is appropriate for certain fields.

Let’s take the phone field as an example. The phone field is one of the things you don’t want to see messed up when a package is out for delivery. To keep it valid, we need to add validations for our phone fields on all forms across the site. And the best and easiest way to do this is to describe all our phone fields in XML form, which is provided by the SFCC ecosystem.

The XML form contains all the data necessary to describe and validate one form field (type, error messages, label, validations, and others) in most of the cases.


Let’s Do Some Work


In this post, we will focus on updating the newsletter subscription form provided with the default SFRA code. It is shown on the homepage of your storefront reference webshop.



The current newsletter form contains one email field (which is usually enough when it comes to newsletters). But let’s say that our client is using a 3rd party service which requires the first name value if the user wants to subscribe to some additional emails and promotions.

SFRA newsletter form is not using the XML form (I don’t know why), so we will convert it to something more SFCC specific.


Where to Start?


To edit this form, we need to choose which file to override. The file responsible for printing a newsletter form for the home page is homePage.isml (What a surprise! :)). As I have previously mentioned, we can see that it is just a plain form with an email where the button and the code are not relying on SFCC forms at all.

How to figure that out? Well, if the form field name is without a dedicated form field variable in isml, and if in DOM there is no HTML input field name like dwfrm_<form name>_<form field id>, then you are looking at regular HTML forms.


<isdecorate template="common/layout/page">


        var assets = require('*/cartridge/scripts/assets.js');





    <div class="home-main homepage">

        <isslot id="home-main-m" description="Main home page slot." context="global" />



    <div class="container home-categories homepage">

        <div class="row home-main-categories no-gutters">

            <isslot id="home-categories-m" description="Categories slots on the home page." context="global" />




    <div class="container home-product-tiles homepage">

        <div class="hp-product-grid" itemtype="" itemid="#product">

            <isslot id="home-products-m" description="Product tiles on the home page." context="global" />




    <div class="homepage shop-the-style">

        <isslot id="home-product-set-m" description="Link to a Product Set." context="global" />


    <div class="home-email-signup">

        <div class="container">

            <div class="row">

                <div class="col-sm-5">

                    <div class="input-group">

                        <isinclude template="home/components/newsletterForm" />








The Real Deal - Forms and Validations


Let’s start by making an XML form. Forms are located in SFRA core allowing you to look at them for some reference about field definitions or just jump to the documentation and check it out.



It is not a new functionality; it is something used from the first pipeline architecture so the documentation describes it nicely.

We need to make the same folder structure in our cartridge. So, let’s add some code in it to describe our fields and rules.


<?xml version="1.0"?>































    <action formid="subscribe" label="button.form.subscribe" valid-form="true"/>


Now we have a basic form that requires a field, and then we can use it in isml and server-side scripting with available SFCC functions.


Some of the fields are mandatory, which means that you need to provide them. I will describe just a few that are “more” important than others.

      - formid - the name of the field which is going to be used to access it

      - type - a field type which is going to be used. We are going to use string and boolean types

      - mandatory - marks the field invalid if there is no value

      - label - used as a translation key to show a message beside the input field

      - binding - it is used when we perform coping details to form an object. This is not used here, but is just worth mentioning

      - validation - path to the custom validation script


There are 2 validation types for form fields we can use. In the first type we can use standard validations like mandatory, min and max length, etc. Those validations will use error labels from attributes missing-error, parse-error, range-error, value-error. Error messages are used per validation they represent, and in sort order provided in the previous sentence when an example custom validation is used.

That takes us to the second type of form and field validations - custom validation scripts. In our example, firstName field is not mandatory, but it becomes mandatory if a checkbox subscribeToSecondEmailList is checked.

To do something like a validation, an attribute is introduced. It should contain a path to the validation script, and one parameter in the function call. The parameter is the “object/context” that is validated. It can be formgroup, and it is used when validation for forms or form groups is performed or formfield for validating simple form fields.

A validator needs to return boolean value or custom dw.web.FormElementValidationResult. If boolean is returned, then messages are used in the order described above. If someone wants to return custom translation, then an instance of FormElementValidationResult needs to be made. Class constructor accepts boolean (success and failure) and message (translation) key.


/* eslint-disable no-undef */

exports.validate = function (form) {

    if (form.subscribeToSecondEmailList.checked && empty(form.firstName.value)) {


        return false;


    return true;


It is always a good approach to have front-end validation as well, and present some kind of validation response on blur, or something similar to a user. Since we are relying on back-end validation here, I will skip customization for custom relations between fields and keep it simple. We will reuse what SFRA provides.


Preparing Home Controller


Standard Home controller doesn’t push our newly created newsletter form to ISML, so we need to extend it, and add our form to viewData.

Besides form, the code will need to have an action endpoint for an HTML form tag passed from the controller. It can be hardcoded in isml, but I prefer to pass it from a controller.

Therefore two properties are pushed to viewData. They are called forms and formActions.


'use strict';

const server = require('server');



server.append('Show', function (req, res, next) {

    const URLUtils = require('dw/web/URLUtils');

    const newsletterForm = server.forms.getForm('newsletter');




        formActions: {

            newsletter: URLUtils.https('EmailSubscribe-Subscribe').toString()


        forms: {

            newsletter: newsletterForm





module.exports = server.exports();

The newsletter form is loaded from the user session and cleared to prevent storing data when the storefront form is submitted. SFCC stores submitted data into session. If we include the same form on the other page, it will be populated on a page load.




Once the form is declared, the controller passes it to the template. This is when we need to use it somehow.

Starting out from homePage.isml, let’s delete the old form code and make one that includes our shiny new form to make the code cleaner.



The form structure with all the validation applied (for FE) requires some things like classes as well as data attributes. Older implementations of SFCC had a module called isinputfield which took care of rendering for HTML input elements.

In SFRA we need to define all classes, data attributes, etc. On several projects we reintroduced our custom isinputfield to SFRA because it was more convenient to use. We will go there with SFRA way and add all the required elements in HTML.



Here we have our subscribe form with 2 input elements and one checkbox. For FE validation we need to print data elements that are used as error messages manually for FE validation. The last row of input field prints attributes like regex, name, etc. from the XML form.




    class="newsletter-form js-newsletter-form"


    <isprint value=${pdict.forms.newsletter.attributes} encoding="off" />>


        let emailRequired = === true;


    <div class="form-group ${emailRequired ? 'required' : ''}">

        <isprint value="${}" encoding="htmlcontent" />






            ${emailRequired ? ' required ' : ''}

            data-range-error="${Resource.msg('error.message.lessthan50', 'forms', null)}"

            data-missing-error="${Resource.msg('error.message.required', 'forms', null)}"



            <isprint value=${} encoding="off" />>

        <div class="invalid-feedback" id="form-newsletter-email-error"></div>




        let fnameRequired = pdict.forms.newsletter.firstName.mandatory === true;


    <div class="form-group ${fnameRequired ? 'required' : ''}">

        <isprint value="${pdict.forms.newsletter.firstName.label}" encoding="htmlcontent" />






            ${fnameRequired ? ' required ' : ''}

            data-missing-error="${Resource.msg('error.message.required', 'forms', null)}"

            data-range-error="${Resource.msg('error.message.lessthan50', 'forms', null)}"


            <isprint value=${pdict.forms.newsletter.firstName.attributes} encoding="off" />>

        <div class="invalid-feedback" id="form-newsletter-fname-error"></div>



    <div class="form-group custom-control custom-checkbox">








        <label class="custom-control-label" for="${pdict.forms.newsletter.subscribeToSecondEmailList.htmlName}">

            <isprint value="${pdict.forms.newsletter.subscribeToSecondEmailList.label}" encoding="htmlcontent" />




    <button type="submit"


        class="btn btn-primary">

        <isprint value="${Resource.msg(pdict.forms.newsletter.subscribe.label, 'forms', null)}" encoding="htmlcontent" />


    <div class="email-description">${Resource.msg('description.form.emailsignup', 'homePage', null)}</div>


Now the form is ready to be checked on our storefront. Javascript front-end form validations are hooked immediately by the system, so we don’t have to do anything additionally.




Every project has a need for static labels that are translated into the appropriate locale. All translations are stored in key/value pairs in .properties files. 

XML forms field label is loading a translation from by using a label field as the key. For our form, we have several translations and they are added to



 to additional 3rd party service name is required to subscribe to additional service



So far we have prepared a newsletter form to be shown for a user on the home page. I won’t focus on styling, and make it too pretty. Let’s just make it fully functional. It should be something similar to this:




Javascript Logic


The old newsletter form was submitted via JS by POSTing data with AJAX. . In order to POST all form fields to the server, we will tackle and adjust the front end javascript code to make it more generic for some future newsletter forms (in case we add more fields). 

Functionality from SFRA is located in components/footer.js, so we need to rewrite it. Since footer is loaded from main.js, main.js needs to be overridden, and footer.js reads from our cartridge and not from the base.




window.jQuery = window.$ = require('jquery');

const processInclude = require('base/util');


$(document).ready(function () {















Footer.js is refactored to be more dynamic with form elements on the newsletter form. HTML form element attributes are used to form XHR request. So, if something is changed in isml (form action, URL, etc.), code will pick it up.

Form validation for FE needs to show error messages from the server underneath the fields. This is why we are going to reuse SFCC formValidation script.

formValidation is expecting form jquery element and the object with key/value pairs where the key is the name of input and the value is an error message which will be shown underneath.

displayMessage function is a bit refactored, but functionality stays similar. It is going to present success or failure message to the user in the form of a small popup.




'use strict';

const $ = window.$;

const scrollAnimate = require('base/components/scrollAnimate');

const formValidation = require('base/components/formValidation');


let emailSignupT = null;


function displayMessage(data, $form) {

    const $button = $form.find('.js-submit-btn');

    let status = data.success ? 'alert-success' : 'alert-danger';

    let $emailSignupMsg = $('.email-signup-message');




    if (!$emailSignupMsg.length) {

        $('body').append('<div class="email-signup-message"></div>');

        $emailSignupMsg = $('.email-signup-message');



    $emailSignupMsg.html('<div class="email-signup-alert text-center ' + status + '">' + data.msg + '</div>');



    emailSignupT = setTimeout(function () {



    }, 3000);



module.exports = function () {

    $('.js-newsletter-form').on('submit', function (e) {



        const $form = $(this);

        const $submitBtn = $form.find('.js-submit-btn');


        $submitBtn.attr('disabled', true);



            url: $form.attr('action'),

            type: $form.attr('method'),

            data: $form.serialize(),

            success: function (data) {

                formValidation($form, data);

                displayMessage(data, $form);


            error: function (err) {

                formValidation($form, err);

                displayMessage(err, $form);





    $('.back-to-top').on('click', scrollAnimate);


I want newsletters! The Controller


Although EmailSubscribe controller code is refactored, it is preserving similar functionality from the core. We can see that check if the form is valid to rely completely on SFCC. This means that we don’t have to do any kind of custom validation here for each field separately.

Email is validated by FE and BE described in newsletter.xml. Besides returning just messages we want to show field errors on the newsletter form to a user. Fields are returned as an additional parameter, and formErrors core script will return key/value mapping of field name and error message back if the field is invalid. This is important for JS so that it can print errors underneath the form elements.




'use strict';

const server = require('server');




server.replace('Subscribe', function (req, res, next) {

    const Resource = require('dw/web/Resource');

    const newsletterForm = server.forms.getForm('newsletter');

    const formErrors = require('*/cartridge/scripts/formErrors');

    const hooksHelper = require('*/cartridge/scripts/helpers/hooks');



        success: false,

        fields: formErrors.getFormErrors(newsletterForm),

        msg: Resource.msg(

            newsletterForm.firstName.valid ? '' : '', 'forms', null




    if (newsletterForm.valid) {

        hooksHelper('app.mailingList.subscribe', 'subscribe', [], function () {});


            success: true,

            msg: Resource.msg('', 'homePage', null)


        return next();


    return next();


module.exports = server.exports();


This is how response from server looks like in case of an invalid form element:





This was just a basic example of how we can use form XML and do BE validations for our code. Keeping most of the validations in XML form will give us cleaner codebase and more reusable parts in our application. This is really helpful if we use multiple sites and locales where some fields like phone, postal code, and others are validated differently per locale.

Here is a short video of the form and how it works.


If you have any questions and doubts, we will be happy to help you with your SFCC implementations. Feel free to reach out.


About the author

Nikola Gorjanac

CTO & Co-Founder at Bee IT

interesting read? Share it!

Latest blog posts

Handling Custom Shipping and Payment Methods in SFCC

You must have had shoppers that abandon their carts at the payment part of the checkout flow. Did it happen because your payment or shipping options didn’t suit them? To increase your conversion rates, you should consider adding new custom payment or shipping options that are not included in the base options of your site. In this guide, you will learn how to add a new custom payment and shipping methods to your Salesforce Commerce Cloud site. We will also show you how you can configure your custom shipping methods to suit your needs perfectly. Read More...

2020 – A Year of Adversity, Adaptation and Learning

This strange year is nearly reaching its end, so it’s a great time to look back at what we have accomplished, but above all learned during 2020. The year has been full of uncertainty and adversity for the entire world, but it is often hard times that offer the biggest lessons and opportunities for growth. Our company’s core values which are shared by all our employees are the foundation of our success, and this year has made us recognize and appreciate some of them even more. Read More...

Getting started with controllers, models and decorators (SFCC)

Controllers were introduced as an update of pipelines and, eventually they replaced them completely. They are one of the most important parts of the Salesforce Commerce Cloud project because they control the flow of data in our application. On the other hand, models fetch data from a server and provide it as a JSON object that will be used to render a page. In this article we will show you how you can build on your existing RefArch site (or SFRA) to add a new functionality with controllers and models. Read More...

Using the full potential of Salesforce Commerce Cloud (SFCC) SEO functionality

In today’s world, it is increasingly important to do search engine optimization on your website because nearly half of customers start their shopping using a search engine. If we want our business to be successful online it is vital to use all available resources that Commerce Cloud offers to optimize your website for search engines. Based on SEO that we can manage, we can divide it into two categories: On-Page SEO and Crawlability. On-Page SEO refers to the keyword strategy that we will apply on on-site content across different pages of our website. It includes storefront URLs, titles, descriptions, H1 tags, Image Alt tags, and other on-site content. Another category we must pay attention to is crawlability, which refers to the ability of search engines to find and index pages on our website. It includes the following elements: sitemaps, canonical tags, robot.txt, redirects, error handling, and 404 pages. Let’s start exploring all that we are offered in Merchant Tools under SEO. Read More...

The Basics of Salesforce Commerce Cloud SEO

Before we start going into basics and best practices of SEO on your Salesforce site, you should also understand URL Request Analyzer. This tool can show you what URL requests are being processed on your storefront so you can see what configuration is being used to open that page. This can help us understand some parts of SEO we are still not familiar with and let us reach our goal faster. Basics of every page: title and description.... Read More...

Salesforce Commerce Cloud OCAPI and Hooks

In this blog, I will give an overview of what hooks actually are, and how they can help in developing great features. Hooks help you a lot when you are in need of dynamic functionality that will execute only at certain times, and only when it&#39;s crucial for your software solution to do so. Hooks listen to certain events in the shop or in the data layer of your storefront. Which events will the hooks listen to is totally up to the development plan and customer needs. Read More...

Creating a breakout custom attribute editor in Page Designer for Salesforce Commerce Cloud (SFCC)

How to implement a custom attribute editor in Salesforce Commerce Cloud? This is what we will focus on in this article. The next logical question would be “Why do I need to implement a custom attribute editor in SFCC?”. Well the answer is quite simple. If your storefront website needs a component which doesn’t have a predefined Page Designer type, implementing a custom attribute editor is the way to go. Read More...