2012-02-17 96 views
5

我目前使用Jquery Validation和Qtip一起使用驗證選項的errorPlacement組件驗證錯誤時,使用漂亮的工具提示樣式通知來處理實際驗證並將信息顯示在屏幕上。Knockout驗證和Qtip

目前,每個viewModel都有自己的自定義方法來設置和啓動驗證和回調,但是我試圖看到一個更好的方式來做到這一點,是它添加一個自定義綁定來設置我的驗證規則通過數據綁定或其他方式,但仍產生相同的結果(即,當驗證錯誤發生時觸發errorPlacement並告知Qtip顯示給定元素的錯誤)。

現在在我開始製作一個自己之前,我剛剛在網上查了一下,發現Knockout Validation,我最初認爲這是一個好主意,我可以將我的驗證邏輯直接應用到viewModel中的數據,然後找到某種回調得到Qtip踢,但似乎沒有回調,我可以找到記錄。圖書館似乎做了我想要的東西的驗證方面的一切,而不是爲了顯示方面的東西。我查看了源代碼和示例,但除ko.validation.group(viewModel)之外無法看到任何可以給我一個包含錯誤的observable的東西,但我不確定是否可以像我一樣使用它期待。

這是我目前的驗證是如何發生的一個例子:

/*globals $ ko */ 
function SomeViewModel() { 

    this.SetupValidation = function() { 
     var formValidationOptions = { 
      submitHandler: self.DoSomethingWhenValid, 
      success: $.noop, 
      errorPlacement: function (error, element) { 
       if (!error.is(':empty')) 
       { qtip.DoSomethingToDisplayValidationErrorForElement(element, error); } 
       else 
       { qtip.DoSomethingToHideValidationErrorForElement(element); } 
      } 
     }; 

     $(someForm).validate(formValidationOptions); 
     this.SetupValidationRules(); 
    }; 

    this.SetupValidationRules = function() { 
     $(someFormElement1).rules("add", { required: true, minlength: 6, maxlength: 20, alphaNumeric: true }); 
     $(someFormElement2).rules("add", { required: true, minlength: 6, maxlength: 20 }); 
     $(someFormElement3).rules("add", { required: true, email: true, }); 
    }; 
} 

目前我確信我可以通過添加自定義綁定,所以我可以設置驗證數據刪除的驗證規則方法的需要綁定,但是如果可能的話,我想在現有的Knockout-Validation綁定中使用同樣的回調方法。

回答

5

我沒有特別使用Knockout-Validation,但過去我寫了類似的東西。快速瀏覽源代碼可以看出,每個擴展的可觀察對象都可以獲得子可觀察的isValid。這可以用於使用傳統的敲除可見綁定來隱藏標記中的顯示消息。

要讓QTip工作,自定義綁定可以訂閱此isValid屬性,並在觸發時執行必要的初始化以顯示/隱藏QTip。

編輯

下面是一個例子,讓你開始

http://jsfiddle.net/madcapnmckay/hfcj7/

HTML:

<!-- Note that you have to reference the "qtipValMessage" binding --> 
<!-- using the "value" binding alone is not enough    --> 
<input data-bind="value: emailAddress, qtipValMessage : emailAddress" /> 

JS:

ko.bindingHandlers.qtipValMessage = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     var observable = valueAccessor(), $element = $(element); 
     if (observable.isValid) { 
      observable.isValid.subscribe(function(valid) { 
       if (!valid) { 
        $element.qtip({ 
         overwrite: true, 
         content: { 
          text: observable.error 
         } 
        }); 
       } else { 
        $element.qtip("destroy"); 
       } 
      }); 
     } 
    } 
}; 
+0

IsValid屬性可能表明出了問題,但我需要有錯誤的數據綁定到這樣我就可以顯示工具提示的元素,沒有元素,我不能做太多。 – Grofit 2012-02-27 09:15:48

+0

因此,需要一個自定義綁定,你可以把它放在你想應用QTip的元素上,然後它可以處理訂閱到的isValid屬性。 – madcapnmckay 2012-02-28 00:44:54

+0

我不喜歡在任何問題上拋出自定義綁定的方法,但這似乎是解決問題的體面方法。目前,我剛剛更改了knockout驗證庫,以將observable添加到group()方法輸出中,並且在驗證允許我訪問時還將每個observables綁定元素附加到該元素上,但是我可能會將其更改爲使用類似於擁有。非常感謝這個例子! – Grofit 2012-02-28 09:21:58

1

我一直在編輯madcapnmckay的帖子,但差異已經變得足夠重要,我認爲需要一個新的答案。

它主要基於madcapnmckay的文章,但它修復了MorganTiley指出的一個錯誤。只有當用戶修改了observable時,原始圖纔有效。如果他們沒有,那麼代碼永遠不會被解僱。所以,我修改了它,以便它在創建時觸發工具提示代碼,除了它發生更改時。

ko.bindingHandlers.qtipValMessage = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     var observable = valueAccessor(), $element = $(element); 
     if (observable.isValid) { 
      var updateTooltip = function (valid) { 
       if (!valid) { 
        $element.qtip({ 
         overwrite: true, 
         content: { 
          text: observable.error 
         } 
        }); 
       } else { 
        $element.qtip("destroy"); 
       } 
      } 
      updateTooltip(); 
      observable.isValid.subscribe(updateTooltip); 
     } 
    } 
}; 

的一個缺點是,工具提示會顯示在懸停淘汰賽驗證已運行(例如之前,你有一個字段是「必需的」確認,按提交提示會顯示話說場前需要,但該領域不會突出粉紅色)。但是,一旦更改了字段,如果字段有效,則工具提示將消失。

我的應用程序不是使用qtip,而是使用Twitter Bootstrap Tooltip,所以這裏也是代碼。

ko.bindingHandlers.invalidTooltip = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     var observable = valueAccessor(), $element = $(element); 
     if (observable.isValid) { 
      var updateTooltip = function (valid) { 
       if (!valid) { 
        $element.attr("data-original-title", observable.error); 
        $element.tooltip(); 

       } else { 
        $element.tooltip("destroy"); 
       } 
      } 
      updateTooltip(); 
      observable.isValid.subscribe(updateTooltip); 
     } 
    } 
};