粘贴文本时,TextChanged的回发不会触发

前端开发 2026-07-10

我在处理这个JavaScript的一个问题:当我粘贴一个数字时,TextChanged的回发不会被触发,而手动输入数值时却能正确触发。
这是一个通用控件,问题可能与回发有关。

js

function verificaIncolla(event, sender) {

    try {
        var clipboardData = (event.clipboardData || window.clipboardData);
        var pasted = clipboardData ? clipboardData.getData('text') : null;

        if (!pasted) {
            return;
        }


        var containsLetter = /[A-Za-z\u00C0-\u024F]/.test(pasted); 
        if (containsLetter) {
            return;
        }

        var cleaned = pasted.replace(/\s+/g, '');

        cleaned = cleaned.replace(/[^0-9\.,\-]/g, '');

        cleaned = cleaned.replace(/-/g, function (m, offset) {
            return (offset === 0) ? '-' : '';
        });

        if (cleaned.indexOf('-') > 0) {
            cleaned = cleaned.replace(/-/g, '');
        }


        var separators = cleaned.match(/[.,]/g);
        if (separators && separators.length > 1) {
            var lastSep = cleaned.lastIndexOf('.') > cleaned.lastIndexOf(',') ? '.' : ',';
            cleaned = cleaned.replace(/[.,]/g, '');
            if (cleaned.length > 2) {
                var before = cleaned.substring(0, cleaned.length - 2);
                var after = cleaned.substring(cleaned.length - 2);
                cleaned = before + lastSep + after;
            } else {
                cleaned = cleaned + lastSep;
            }
        }

        var start = sender.selectionStart;
        var end = sender.selectionEnd;
        var value = sender.value || "";
        var newValue = value.substring(0, start) + cleaned + value.substring(end);
        sender.value = newValue;

        var newCaret = start + cleaned.length;
        if (typeof sender.setSelectionRange === 'function') {
            sender.setSelectionRange(newCaret, newCaret);
        }

        replaceAllDot(sender);
        VerificaTestoImporto(sender);
        if (typeof formattaNumero === 'function') {
            try { formattaNumero(sender,2); } catch (e) {  }
        }

    } catch (e) {
        console.error('verificaIncolla error:', e);
        }
}
     <asp:TextBox CssClass="form-control" OnTextChanged="txtDecimale_TextChanged" runat="server" ID="txtDecimale"  onkeyup="VerificaTestoImporto(this)" onfocus="replaceAllDot(this);"  onpaste="verificaIncolla(event,this)" ></asp:TextBox>

如果我从文本框移除 onpaste 事件,TextChanged的回发就会被正确触发。

解决方案

问题在于 verificaIncolla 函数直接通过JavaScript设置了 sender.value,这不会触发浏览器原生的 change 事件,因此ASP.NET的 AutoPostBack依赖该事件的触发。

修复方法是在设置值后派发一个 input 和一个 change 事件。

以下是在你的函数中的修复。

function verificaIncolla(event, sender) {
    try {
        var clipboardData = (event.clipboardData || window.clipboardData);
        var pasted = clipboardData ? clipboardData.getData('text') : null;

        if (!pasted) {
            return;
        }

        var containsLetter = /[A-Za-z\u00C0-\u024F]/.test(pasted);
        if (containsLetter) {
            return;
        }

        var cleaned = pasted.replace(/\s+/g, '');
        cleaned = cleaned.replace(/[^0-9\.,\-]/g, '');
        cleaned = cleaned.replace(/-/g, function (m, offset) {
            return (offset === 0) ? '-' : '';
        });

        if (cleaned.indexOf('-') > 0) {
            cleaned = cleaned.replace(/-/g, '');
        }

        var separators = cleaned.match(/[.,]/g);
        if (separators && separators.length > 1) {
            var lastSep = cleaned.lastIndexOf('.') > cleaned.lastIndexOf(',') ? '.' : ',';
            cleaned = cleaned.replace(/[.,]/g, '');
            if (cleaned.length > 2) {
                var before = cleaned.substring(0, cleaned.length - 2);
                var after = cleaned.substring(cleaned.length - 2);
                cleaned = before + lastSep + after;
            } else {
                cleaned = cleaned + lastSep;
            }
        }

        var start = sender.selectionStart;
        var end = sender.selectionEnd;
        var value = sender.value || "";
        var newValue = value.substring(0, start) + cleaned + value.substring(end);
        sender.value = newValue;

        var newCaret = start + cleaned.length;
        if (typeof sender.setSelectionRange === 'function') {
            sender.setSelectionRange(newCaret, newCaret);
        }

        replaceAllDot(sender);
        VerificaTestoImporto(sender);
        if (typeof formattaNumero === 'function') {
            try { formattaNumero(sender, 2); } catch (e) { }
        }

        // Fire input + change events so ASP.NET AutoPostBack is triggered
        sender.dispatchEvent(new Event('input', { bubbles: true }));
        sender.dispatchEvent(new Event('change', { bubbles: true }));

    } catch (e) {
        console.error('verificaIncolla error:', e);
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章