簡體   English   中英

如何在本機驗證事件流中調用自定義約束驗證?

[英]How do I invoke custom constraint validation as part of the native validation event flow?

  • 以下基於對Chrome 31的測試
  • TL; DR:在代碼為什么這個小提琴作品上嘗試提交,但不會在這一塊上手動調用? 有更好的方法嗎?

在回答一個問題,要求針對其accept屬性驗證<input type="file"> (本機行為將與結果文件對話框配合使用,以默認顯示過濾器,但未強制執行)時,我希望了解哪些選項可用於將此自定義驗證集成到HTML5的腳本化約束驗證中

我最初對API的略讀使我覆蓋了本地的checkValidity方法,並認為只要瀏覽器認為適合驗證代碼( jsFiddle ),就會默認調用該方法:

void function enhanceFileInputTypeValidityCheck(){
    var inputPrototype      = document.createElement( 'input' ).constructor.prototype;
    var nativeCheckValidity = inputPrototype.checkValidity;

    // This is my custom validation function
    function validateFileInputType( input ){
        var MIMEtype = new RegExp( input.accept.replace( '*', '.\*' ) );

        return Array.prototype.every.call( input.files, function passesAcceptedFormat( file ){
            return MIMEtype.test( file.type );
        } );
    }

    // My attempt at getting the behaviour to happen 
    inputPrototype.checkValidity = function enhancedCheckValidity(){
        if( this.type === 'file' &&  this.accept && this.files && this.files.length ){
            if( !validateFileInputType( this ) ){
                this.setCustomValidity( 'Please only submit files of type ' + this.accept );

                return false;
            }
        }

        return nativeCheckValidity.apply( this );
    }
}();

這有效地增強了checkValidity使其在不滿足我的條件時返回false ,並且在滿足條件時會陷入本機行為,但setCustomValidity不能按預期工作:它不會引發任何異常,但不會顯示任何錯誤消息無論是。 至關重要的是,我在checkValidityreturn false不會阻止表單提交。

經過一番擺弄之后,我最終得到了這個事件處理程序,該事件處理程序與上面發布的代碼一起最終實現了預期的目標,即防止根據自定義條件提交並反饋給用戶( jsFiddle ):

$( 'input' ).on( 'change input', function( event ){
    this.checkValidity();
} );

我對這種情況的發生感到迷惑:根據記錄事件類型, change將執行checkValidity ,但不會顯示該消息; 同時嘗試提交表單確實實現了我的setCustomValidity ,但不會記錄事件類型:但是,這意味着這是一個input事件,因為這是處理程序正在偵聽的唯一其他事件-但是(這就是它在哪里變得奇怪),不受change約束(無論如何都無法正常工作),僅將input作為命令式回調的觸發器就不再阻止提交了

我仍然對將我的自定義驗證綁定到本機驗證流中的“正確”方式不知所措,因為綁定changeevent以觸​​發預期行為(當這兩個事件均未發生時)似乎太過棘手了預期用途。

獎勵積分,用於解釋以下任何一項:

  • 在空輸入上調用checkValidity時,為什么我的自定義驗證console.log沒有得到任何反饋?
  • 為什么在綁定到input && change的事件處理程序中,我沒有從console.log獲得任何反饋?
  • 為什么執行代碼作為change事件的回調不會觸發setCustomValidity
  • 什么事件(如果未input )實際上觸發了我的setCustomValidity
  • 我可以在不覆蓋checkValidity情況下產生相同的期望最終結果嗎?

據我所知,checkValidity方法調用瀏覽器的內部驗證,而不是瀏覽器的內部驗證調用。 因此,如果您覆蓋它,瀏覽器將不會注意到或關心。

以我的經驗,實現自定義有效性的所有必要操作是綁定到更改事件,然后使用正確的值調用setCustomValidity。 例如,

myinput.addEventListener('change', function(e) {
    if ( ! myCustomValidityCheck() )
        this.setCustomValidity( 'Uh oh, that didn\'t work!' );
    else
        this.setCustomValidity( '' );
})

異想天開的JSFiddle示例

這是您的問題的解決方案http://jsfiddle.net/trixta/E7VtD/

  1. 使用輸入事件的更改提示。 輸入事件很好,但不適用於input [type = file]。
  2. 您不應覆蓋checkValidity
  3. 在dom准備就緒和每次更改時使用setCustomValidity
  4. 使用reportValidity(如果可用)來報告錯誤或通過單擊提交按鈕來模擬reportValditity

這是使setCustomValidity更簡單的簡單方法:

//setCustomValidity is stupid so we improve by adding setCustomValidityRule
$.fn.setCustomValidityRule = function (type, rule) {
    var testRule = function () {
        //only if it's valid or we have set the message our own
        if ($(this).is(':valid') || $.data(this, 'customErrorType' + type)) {
            var message = rule(this);
            this.setCustomValidity(message);
            if (message) {
                $.data(this, 'customErrorType' + type, message)
            } else {
                $.removeData(this, 'customErrorType' + type);
            }
        }
    };
    return this
    //invoke initially
    .each(testRule)
    //and on every change
    .on('customchange.customerror' + type + ' change.customerror' + type, testRule);
};

這是一種使reportValidity在當前瀏覽器中工作的方法:

$.fn.reportValidity = function () {
    return this.each(function () {
        var form;
        if (this.reportValidity) {
            this.reportValidity();
        } else {
            form = $($.prop(this, 'form')).add(this).filter('form');
            //checkvalidity is obtrusive sometimes so we use :invalid
            if($(':invalid', form).length){
            $('<input type="submit" />')
                .css({
                    position: 'absolute',
                    left: '-99999px'
                })
                .appendTo(form)
                .click()
                .remove();
            }
        }
    });
};

我將嘗試總結一下我的經驗:

  1. 自定義驗證檢查應同時在用戶數據輸入和表單提交按鈕單擊上執行。
  2. 您需要同時使用HTML5表單驗證API中的setCustomValiditycheckValidity方法。
  3. 為了驗證用戶數據輸入,您可以在輸入字段元素中添加一個input事件偵聽器,該input事件偵聽setCustomValidity在輸入字段上調用setCustomValidity setCustomValidity的參數中,您調用一個合適的檢查函數,如果用戶輸入有效,則該函數返回空字符串,否則返回約束違反消息。
  4. 為了在單擊表單提交按鈕時進行驗證,您checkValidity在表單元素上調用checkValidity ,並且僅在返回true時才繼續提交。

另請參閱我對類似SO問題的回答嘗試我的示例解決方案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM