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

ASP.NET Core表单克隆后无法切换intl-tel-input国家选项问题

问题解决:克隆表单后intl-tel-input无法切换国家及号码获取方案

问题根源

  1. 重复ID冲突:原表单的input带有固定ID(contact-phone/fax-contact),克隆后出现多个相同ID元素,导致JS选择器无法正确定位新元素。
  2. 克隆残留插件DOM:直接克隆包含intl-tel-input生成的额外DOM(如国家选择下拉框)的表单,会引发新旧实例的事件与DOM结构冲突,无法正常触发国家切换。
  3. 实例初始化逻辑问题:销毁实例的时机错误,克隆后的元素残留旧实例绑定,导致新实例初始化失败。

修正后的代码实现

视图部分(移除固定ID,保留类选择器)

<div id="contact-forms-container">
    <!-- 初始联系表单 -->
    <div class="form-card contact-form-card">
        <h5 class="form-title">Contact 1</h5>
        <form>
            <div class="form-row align-items-center">
                <div class="col-md-6 mb-3">
                    <label>Phone number</label>
                    <!-- 移除固定ID,仅保留类 -->
                    <input type="text" class="form-control contact-phone" placeholder="Phone number">
                </div>
                <div class="col-md-6 mb-3">
                    <label>Fax</label>
                    <input type="text" class="form-control fax-contact" placeholder="Fax">
                </div>
            </div>
            <button type="button" class="btn btn-danger remove-form-button">移除</button>
        </form>
    </div>
</div>
<button type="button" id="add-another-contact-form" class="btn btn-primary mt-3">添加新联系人表单</button>

JS部分(修复克隆逻辑、实例初始化及号码获取)

$(document).ready(function () {
    var contactCounter = 2;

    // 初始化第一个表单
    initializeForm($(".contact-form-card").first());

    $("#add-another-contact-form").on("click", function () {
        // 基于初始表单克隆并重置状态
        const originalForm = $(".contact-form-card").first().clone();
        const clonedForm = resetFormForClone(originalForm);
        
        // 设置新表单标题
        clonedForm.find(".form-title").text(`Contact ${contactCounter}`);
        // 绑定移除事件
        clonedForm.find(".remove-form-button").on("click", function () {
            // 移除前销毁插件实例
            destroyFormInstances(clonedForm);
            clonedForm.remove();
        });

        // 添加到容器并初始化插件
        $("#contact-forms-container").append(clonedForm);
        initializeForm(clonedForm);
        contactCounter++;
    });

    // 重置克隆表单,清理插件生成的DOM和输入值
    function resetFormForClone(form) {
        form.find(".iti").remove();
        form.find(".contact-phone, .fax-contact").val("").removeClass("iti-input");
        return form;
    }

    // 销毁表单内的插件实例,避免内存泄漏
    function destroyFormInstances(form) {
        const phoneInput = form.find(".contact-phone");
        const faxInput = form.find(".fax-contact");
        
        if (phoneInput.data("itiContact")) {
            phoneInput.data("itiContact").destroy();
            phoneInput.removeData("itiContact");
        }
        if (faxInput.data("itiFax")) {
            faxInput.data("itiFax").destroy();
            faxInput.removeData("itiFax");
        }
    }

    // 初始化表单的intl-tel-input插件
    function initializeForm(form) {
        const phoneInput = form.find(".contact-phone");
        const faxInput = form.find(".fax-contact");

        // 初始化电话输入框
        const itiContact = window.intlTelInput(phoneInput[0], {
            formatOnDisplay: true,
            separateDialCode: true,
            hiddenInput: `full_phone_${contactCounter - 1}`, // 唯一命名隐藏输入,避免提交冲突
            utilsScript: "https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.8/js/utils.js"
        });

        // 初始化传真输入框
        const itiFax = window.intlTelInput(faxInput[0], {
            formatOnDisplay: true,
            separateDialCode: true,
            hiddenInput: `full_fax_${contactCounter - 1}`,
            utilsScript: "https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.8/js/utils.js"
        });

        // 存储实例到元素数据,方便后续调用
        phoneInput.data("itiContact", itiContact);
        faxInput.data("itiFax", itiFax);

        // 国家切换事件:获取选中国家代码和完整号码
        phoneInput.on("countrychange", function () {
            const countryData = itiContact.getSelectedCountryData();
            const fullNumber = itiContact.getNumber();
            console.log(`电话:国家代码${countryData.dialCode},完整号码${fullNumber}`);
        });

        faxInput.on("countrychange", function () {
            const countryData = itiFax.getSelectedCountryData();
            const fullNumber = itiFax.getNumber();
            console.log(`传真:国家代码${countryData.dialCode},完整号码${fullNumber}`);
        });
    }
});

关键修改说明

  1. 移除重复ID:所有input仅保留类选择器,规避ID冲突导致的元素定位错误。
  2. 克隆前清理DOM:克隆表单时先移除插件生成的.iti容器,确保新表单从原始input状态初始化,避免旧实例残留。
  3. 唯一隐藏输入名:hiddenInput使用带计数器的命名,确保提交时每个表单的完整号码不会被覆盖。
  4. 实例销毁逻辑:移除表单前先销毁对应的intl-tel-input实例,避免内存泄漏。
  5. 直接获取实例数据:通过插件实例的getSelectedCountryData()和getNumber()方法,直接获取国家代码与完整号码,无需额外存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:55:09