You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Javascript表单验证求助:自定义字段校验与错误提示实现

表单验证逻辑修复方案

问题背景

已有大量JavaScript表单验证相关内容,但未找到适配当前场景的方案。无法访问页面HTML与CSS,仅能添加JS代码。原表单包含Email、Password、Confirm Password字段,已通过JS新增First Name和Last Name字段。需求如下:

  • 点击按钮时校验所有字段非空、密码匹配
  • 若存在错误,显示红色alert block并为每个缺失字段添加对应<li>错误项
  • 校验通过则将First Name和Last Name存入localStorage,并触发隐藏的原生提交按钮

目前已完成字段添加与本地存储功能,仅验证逻辑存在问题,现有代码如下:

$(document).ready(function () {
    function insertBefore(referenceNode, newNode) {
        referenceNode.parentNode.insertBefore(newNode, referenceNode);
    }

    //Change the heading text
    var title = document.getElementById("ContentContainer_MainContent_MainContent_RegisterLocalFormHeading").parentNode.querySelector(".xrm-attribute-value");
    title.innerText = "Register for a CEDA account";

    //Add the firstname & lastname fields above email field.
    var email = document.getElementById("ContentContainer_MainContent_MainContent_ShowEmail");
    var lastname = document.createElement('div');
    lastname.id = "LastName";
    lastname.classList.add("form-group");
    lastname.innerHTML = "<label class='col-sm-4 control-label required' for='LastNameTextBox'><span id='ContentContainer_MainContent_MainContent_LastNameLabel'><span class='xrm-editable-text xrm-attribute'><span class='xrm-attribute-value'>Last Name</span></span></span></label><div class='col-sm-8'><input name='ctl00$ctl00$ContentContainer$MainContent$MainContent$LastNameTextBox' type='text' autocomplete='off' id='LastNameTextBox' class='form-control' aria-required='true'></div></div>";
    insertBefore(email, lastname)
    var firstname = document.createElement('div');
    firstname.id = "FirstName";
    firstname.classList.add("form-group");
    firstname.innerHTML = "<label class='col-sm-4 control-label required' for='FirstNameTextBox'><span id='ContentContainer_MainContent_MainContent_FirstNameLabel'><span class='xrm-editable-text xrm-attribute'><span class='xrm-attribute-value'>First Name</span></span></span></label><div class='col-sm-8'><input name='ctl00$ctl00$ContentContainer$MainContent$MainContent$FirstNameTextBox' type='text' autocomplete='off' id='FirstNameTextBox' class='form-control' aria-required='true'></div></div>";
    insertBefore(lastname, firstname);

    //Add our fake Register button & hide the actual button
    var regButton = document.createElement('input');
    regButton.id = "customSubmitButton";
    regButton.classList.add("btn", "btn-success");
    regButton.setAttribute("name", "ctl00$ctl00$ContentContainer$MainContent$MainContent$customSubmitButton");
    regButton.setAttribute("value", "Register");
    insertBefore(document.getElementById("SubmitButton"), regButton);
    var submitButton = document.getElementById("SubmitButton");
    submitButton.style.visibility = "hidden";

    //Create our Alert\Error Box
    var errorBox = document.createElement('div');
    errorBox.id = "validationSummary";
    errorBox.classList.add("listStyleTypeNone", "alert", "alert-block", "alert-danger");
    errorBox.innerHTML = "<ul role='presentation'></ul>";
    var heading = document.getElementsByClassName("login-heading-section")[0];
    heading.parentNode.insertBefore(errorBox, heading.nextSibling);
    errorBox.style.display = "none";

    regButton.onclick = saveData;
    function saveData() {
        validateForm();
        errorBox.style.display = "block";


        localStorage.setItem("CEDAFName", document.getElementById("FirstNameTextBox").value);
        localStorage.setItem("CEDALName", document.getElementById("LastNameTextBox").value);
        //$("SubmitButton").click();
    }

    function validateForm() {
        var errfirstname, errlastname, errEmail, errPass1, errPass2;
        if ($("#FirstNameTextBox").valid() == false) {
            errfirstname = "<li>First Name is a required field</li>";
        }
        if ($("#LastNameTextBox").valid() == false) {
            errlastname = "<li>Last Name is a required field</li>"
        }

    }

});

修复后的完整代码

$(document).ready(function () {
    function insertBefore(referenceNode, newNode) {
        referenceNode.parentNode.insertBefore(newNode, referenceNode);
    }

    // 修改标题文本
    var title = document.getElementById("ContentContainer_MainContent_MainContent_RegisterLocalFormHeading").parentNode.querySelector(".xrm-attribute-value");
    title.innerText = "Register for a CEDA account";

    // 在邮箱字段上方添加姓和名字段
    var email = document.getElementById("ContentContainer_MainContent_MainContent_ShowEmail");
    var lastname = document.createElement('div');
    lastname.id = "LastName";
    lastname.classList.add("form-group");
    lastname.innerHTML = "<label class='col-sm-4 control-label required' for='LastNameTextBox'><span id='ContentContainer_MainContent_MainContent_LastNameLabel'><span class='xrm-editable-text xrm-attribute'><span class='xrm-attribute-value'>Last Name</span></span></span></label><div class='col-sm-8'><input name='ctl00$ctl00$ContentContainer$MainContent$MainContent$LastNameTextBox' type='text' autocomplete='off' id='LastNameTextBox' class='form-control' aria-required='true'></div></div>";
    insertBefore(email, lastname)
    var firstname = document.createElement('div');
    firstname.id = "FirstName";
    firstname.classList.add("form-group");
    firstname.innerHTML = "<label class='col-sm-4 control-label required' for='FirstNameTextBox'><span id='ContentContainer_MainContent_MainContent_FirstNameLabel'><span class='xrm-editable-text xrm-attribute'><span class='xrm-attribute-value'>First Name</span></span></span></label><div class='col-sm-8'><input name='ctl00$ctl00$ContentContainer$MainContent$MainContent$FirstNameTextBox' type='text' autocomplete='off' id='FirstNameTextBox' class='form-control' aria-required='true'></div></div>";
    insertBefore(lastname, firstname);

    // 添加自定义注册按钮并隐藏原生提交按钮
    var regButton = document.createElement('input');
    regButton.id = "customSubmitButton";
    regButton.classList.add("btn", "btn-success");
    regButton.setAttribute("name", "ctl00$ctl00$ContentContainer$MainContent$MainContent$customSubmitButton");
    regButton.setAttribute("value", "Register");
    insertBefore(document.getElementById("SubmitButton"), regButton);
    var submitButton = document.getElementById("SubmitButton");
    submitButton.style.visibility = "hidden";

    // 创建错误提示框
    var errorBox = document.createElement('div');
    errorBox.id = "validationSummary";
    errorBox.classList.add("listStyleTypeNone", "alert", "alert-block", "alert-danger");
    errorBox.innerHTML = "<ul role='presentation'></ul>";
    var heading = document.getElementsByClassName("login-heading-section")[0];
    heading.parentNode.insertBefore(errorBox, heading.nextSibling);
    errorBox.style.display = "none";

    regButton.onclick = saveData;
    function saveData() {
        // 清空之前的错误提示
        const errorList = errorBox.querySelector('ul');
        errorList.innerHTML = '';
        errorBox.style.display = "none";

        const isValid = validateForm(errorList);
        
        if (isValid) {
            // 校验通过:存储数据并触发原生提交
            localStorage.setItem("CEDAFName", document.getElementById("FirstNameTextBox").value.trim());
            localStorage.setItem("CEDALName", document.getElementById("LastNameTextBox").value.trim());
            submitButton.click();
        } else {
            // 显示错误提示框
            errorBox.style.display = "block";
        }
    }

    function validateForm(errorList) {
        let isValid = true;
        // 获取所有字段的值(去除首尾空格)
        const firstNameVal = document.getElementById("FirstNameTextBox").value.trim();
        const lastNameVal = document.getElementById("LastNameTextBox").value.trim();
        const emailVal = document.getElementById("ContentContainer_MainContent_MainContent_ShowEmail").querySelector('input').value.trim();
        const passwordVal = document.getElementById("ContentContainer_MainContent_MainContent_Password").querySelector('input').value.trim();
        const confirmPassVal = document.getElementById("ContentContainer_MainContent_MainContent_ConfirmPassword").querySelector('input').value.trim();

        // 校验First Name非空
        if (!firstNameVal) {
            const li = document.createElement('li');
            li.textContent = "First Name is a required field";
            errorList.appendChild(li);
            isValid = false;
        }

        // 校验Last Name非空
        if (!lastNameVal) {
            const li = document.createElement('li');
            li.textContent = "Last Name is a required field";
            errorList.appendChild(li);
            isValid = false;
        }

        // 校验Email非空
        if (!emailVal) {
            const li = document.createElement('li');
            li.textContent = "Email is a required field";
            errorList.appendChild(li);
            isValid = false;
        }

        // 校验Password非空
        if (!passwordVal) {
            const li = document.createElement('li');
            li.textContent = "Password is a required field";
            errorList.appendChild(li);
            isValid = false;
        }

        // 校验Confirm Password非空且与密码匹配
        if (!confirmPassVal) {
            const li = document.createElement('li');
            li.textContent = "Confirm Password is a required field";
            errorList.appendChild(li);
            isValid = false;
        } else if (confirmPassVal !== passwordVal) {
            const li = document.createElement('li');
            li.textContent = "Passwords do not match";
            errorList.appendChild(li);
            isValid = false;
        }

        return isValid;
    }
});

核心修改点说明

  • 错误提示重置:每次点击按钮先清空错误列表,避免旧错误残留
  • 完整字段覆盖:新增Email、Password、Confirm Password的非空校验,以及密码匹配校验逻辑
  • 校验状态控制:通过isValid变量统一管理校验结果,只有全部字段通过校验才执行存储和原生提交操作
  • 移除无效依赖:原代码中使用的$.valid()需要依赖jQuery Validate插件,直接通过字段值判断更可靠,避免依赖未加载的第三方库
  • 错误项创建优化:使用原生DOM方法创建错误<li>元素,避免字符串拼接的潜在安全问题与DOM操作风险

内容的提问来源于stack exchange,提问作者BlissSol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:32:01