mcpField
B
b2c-forms

b2c-forms

github.com/salesforcecommercecloud开发5785 次安装今天更新
代码仓库

关于 b2c-forms

面向 Salesforce B2C Commerce 开发者的表单技能,介绍如何按 SFRA 模式创建和验证表单,涵盖 XML 定义、控制器处理、ISML 模板、本地化及提交保护。

主要功能

  1. 01在 XML 中定义字段和验证规则
  2. 02在 SFRA 控制器中处理表单
  3. 03使用 ISML 模板呈现表单
  4. 04本地化标签和错误消息
  5. 05实施 CSRF 防护和服务器端验证

适用场景

  1. 01创建个人资料或联系表单
  2. 02验证提交的表单数据
  3. 03构建 AJAX 表单提交
  4. 04支持本地化的表单标签和错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/salesforcecommercecloud/b2c-developer-tooling --skill b2c-forms

安装后在 Claude Code 中输入/b2c-forms确认已加载。

附带文件evals/trigger-evals.jsonreferences/FORM-XML.md

详细介绍

表单技能

此技能将指导你使用 SFRA 模式在 Salesforce B2C Commerce 中创建带验证的表单。

概述

B2C Commerce 表单由三部分组成:

  1. 表单定义 - 定义字段、验证和操作的 XML 文件
  2. 控制器逻辑 - 服务端表单处理与提交处理
  3. 模板 - 用于渲染 HTML 表单的 ISML 模板

文件位置

表单位于 cartridge 的 forms 目录中:

/my-cartridge
    /cartridge
        /forms
            /default              # Default locale
                profile.xml
                contact.xml
            /de_DE               # German-specific (optional)
                address.xml

表单定义(XML)

基本结构
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.demandware.com/xml/form/2008-04-19">
    <field formid="email" label="form.email.label" type="string"
           mandatory="true" max-length="50"
           regexp="^[\w.%+-]+@[\w.-]+\.\w{2,6}$"
           parse-error="form.email.invalid"/>

    <field formid="password" label="form.password.label" type="string"
           mandatory="true" min-length="8" max-length="255"
           missing-error="form.password.required"/>

    <field formid="rememberMe" label="form.remember.label" type="boolean"/>

    <action formid="submit" valid-form="true"/>
    <action formid="cancel" valid-form="false"/>
</form>
字段类型
类型描述HTML 输入
string文本输入<input type="text">
integer整数<input type="number">
number小数<input type="number">
boolean复选框<input type="checkbox">
date日期值<input type="date">
关键字段属性
属性用途示例
formid字段标识符(必填)formid="email"
label标签的资源键label="form.email.label"
type数据类型(必填)type="string"
mandatory必填字段mandatory="true"
max-length最大字符串长度max-length="100"
min-length最小字符串长度min-length="8"
regexp验证模式regexp="^\d{5}$"
验证错误消息
属性触发时机
missing-error必填字段为空
parse-error值与正则表达式或类型不匹配
range-error值超出最小值/最大值范围
value-error常规验证失败

完整的字段属性、分组、列表和验证模式,请参阅 表单 XML 参考。

控制器逻辑(SFRA)

渲染表单
'use strict';

var server = require('server');
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');

server.get('Show',
    csrfProtection.generateToken,
    function (req, res, next) {
        var form = server.forms.getForm('profile');
        form.clear();  // Reset previous values

        res.render('account/profile', {
            profileForm: form
        });
        next();
    }
);

module.exports = server.exports();
处理表单提交
server.post('Submit',
    server.middleware.https,
    csrfProtection.validateAjaxRequest,
    function (req, res, next) {
        var form = server.forms.getForm('profile');

        if (!form.valid) {
            res.json({
                success: false,
                fields: getFormErrors(form)
            });
            return next();
        }

        // Access form values
        var email = form.email.value;
        var firstName = form.firstName.value;

        // Process and save data
        this.on('route:BeforeComplete', function () {
            var Transaction = require('dw/system/Transaction');
            Transaction.wrap(function () {
                customer.profile.email = email;
                customer.profile.firstName = firstName;
            });
        });

        res.json({ success: true });
        next();
    }
);

function getFormErrors(form) {
    var errors = {};
    Object.keys(form).forEach(function (key) {
        if (form[key] && form[key].error) {
            errors[key] = form[key].error;
        }
    });
    return errors;
}
预填充表单
server.get('Edit', function (req, res, next) {
    var form = server.forms.getForm('profile');
    form.clear();

    var profile = req.currentCustomer.profile;
    form.firstName.value = profile.firstName;
    form.lastName.value = profile.lastName;
    form.email.value = profile.email;

    res.render('account/editProfile', { profileForm: form });
    next();
});

模板(ISML)

基本表单模板
<form action="${pdict.actionUrl}" method="POST" name="profile-form"
      class="form-horizontal" data-action="${URLUtils.url('Profile-Submit')}">

    
    <input type="hidden" name="${pdict.csrf.tokenName}" value="${pdict.csrf.token}"/>

    <div class="form-group ${pdict.profileForm.email.mandatory ? 'required' : ''}">
        <label for="email" class="form-control-label">
            ${Resource.msg('form.email.label', 'forms', null)}
        </label>
        <input type="email"
               id="email"
               name="email"
               class="form-control ${pdict.profileForm.email.error ? 'is-invalid' : ''}"
               value="${pdict.profileForm.email.value || ''}"
               <isif condition="${pdict.profileForm.email.mandatory}">required</isif>
               maxlength="${pdict.profileForm.email.maxLength || 50}"/>
        <isif condition="${pdict.profileForm.email.error}">
            <div class="invalid-feedback">${pdict.profileForm.email.error}</div>
        </isif>
    </div>

    <button type="submit" class="btn btn-primary">
        ${Resource.msg('button.submit', 'forms', null)}
    </button>
</form>

本地化

表单标签和错误消息使用资源包:

forms.properties:

form.email.label=Email Address
form.email.required=Email is required
form.email.invalid=Please enter a valid email address
form.password.label=Password
button.submit=Submit

forms_de_DE.properties:

form.email.label=E-Mail-Adresse
form.email.required=E-Mail ist erforderlich

最佳实践

  1. 提交表单时始终使用 CSRF 保护
  2. 显示表单前清除表单,以重置状态
  3. 标签和错误消息使用资源键(本地化)
  4. 即使使用客户端验证,也要在服务端验证
  5. 数据库操作使用 route:BeforeComplete
  6. AJAX 表单提交时返回 JSON

详细参考

如需了解完整的表单模式:

评论

支持 Markdown