如何在验证后更新ViewModel

时间:2012-12-10 10:58:41

标签: knockout.js knockout-2.0

我正在尝试使用对话框构建用户网格功能,以便编辑用户详细信息。 这是我的HTML:

<!DOCTYPE html>
<html>
<head>
 <script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-   2.1.0.js"></script>
 <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css" rel ="stylesheet" type="text/css" />
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
 <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js">  </script>
 <meta charset=utf-8 />
 <title>JS Bin</title>
</head>
<body>
users:<hr/>
  <div data-bind="foreach:users">
  <div><span data-bind="text:firstname"></span>&nbsp;<a href="#" data- bind="click:EditUser">edit</a></div><hr>
   </div>

   <div id="dialog" style="display:none" data-bind="with:selectedUser">
      <input type="text" data-bind="value:firstname" name="firstname"/>
     <button data-bind="click:validate">save</button>
 </div>
 </body>
 </html>

这是我的JS:

var userVM=function(nm){
  this.firstname=ko.observable(nm); 
  this.EditUser=function(u){
     selectedUser(u);
    $("#dialog").dialog();
 }
};
var users=ko.observableArray([new userVM('Sholmo'),new userVM('Ahmed')]) ;

var selectedUser=ko.observable();
 var validate=function (){
 if($('[name="firstname"]').val()==''){

 alert('must enter name');
 //how prevent model updating?
 }
}

ko.applyBindings();

我的问题是我只想更新用户详细信息 AFTER “保存”按钮点击并验证通过,(现在用户名更新了输入中的文字后立即更新) 这里是jsbin的链接:http://jsbin.com/epocov/1/edit

3 个答案:

答案 0 :(得分:1)

Knockout挂钩输入框中的事件,以便在焦点进入按钮之前更新视图模型。因此,你在验证功能中放置的内容并不重要 - 为时已晚!但你可能已经想到了......

我建议您查看Knockout的第三方插件之一,它可以帮助您进行验证或延期更新:

答案 1 :(得分:0)

使用writeable computed observable,并将您的验证放在写函数中。

例如:

function MyViewModel() {
    this.firstName = ko.observable('Planet');
    this.lastName = ko.observable('Earth');

    this.fullName = ko.computed({
        read: function () {
            return this.firstName() + " " + this.lastName();
        },
        write: function (value) {
            //**Validate here**
            var lastSpacePos = value.lastIndexOf(" ");
            if (lastSpacePos > 0) { // Ignore values with no space character
                this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
                this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
            }
        },
        owner: this
    });
}

答案 2 :(得分:0)

感谢所有试图提供帮助的人,似乎我带来了自己的解决方案...... 这对我有好处,因为通过这种方式,在点击“保存”按钮并通过验证之前,网格中编辑的用户详细信息无法更改: 这是我的解决方案: JS:

   ko.bindingHandlers.updateWhenValid = {

        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    $(element).val(ko.utils.unwrapObservable(valueAccessor()));
        },
        update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
          var value = valueAccessor();
          var valueUnwrapped = ko.utils.unwrapObservable(value);
          $('button').click(function(){
            if($(element).val()!=''){ 
               value($(element).val()); 
               $("#dialog").dialog('close');
            }
            else{ 
             value(valueUnwrapped);
            }  
          });   
        }
    };

    var userVM=function(nm){
    var self=this;  

      this.firstname= ko.observable(nm);

      this.EditUser=function(u){


        selectedUser(u);
        $("#dialog").dialog();
      };


    }; 
    var users=ko.observableArray([new userVM('Shlomo'),new userVM('Ahmed')]) ;

    var selectedUser=ko.observable();



    ko.applyBindings(); 

HTML:

  users:<hr/>
 <div data-bind="foreach:users">
   <div><span data-bind="text:firstname"></span>&nbsp;<a href="#" data-bind="click:EditUser">edit</a></div>
  <hr>
</div>


<div id="dialog" style="display:none" data-bind="with:selectedUser">

  <input type="text" data-bind="updateWhenValid:firstname" />



<button >save</button>

</div>

这样原始值(在对话框打开之前)保持以防验证失败   在这里你可以看到工作演示:

http://jsbin.com/epocov/9/edit