2013-03-08 63 views
0

我有以下代码,我试图使用可写计算observable来验证用户输入,并自动拒绝无效输入。 这只是一些测试代码,我试图阻止用户从文本中删除逗号字符。如果用户删除了逗号字符,我试图将编辑器重新绑定到之前的值以覆盖最近的更改。 这可能使用可写计算字段吗? 我遇到的问题是只有当我加载页面(手动设置ValidText道具之后)时,可写的计算绑定才会触发。但是,当用户键入编辑器时,我无法启动它。KnockoutJS:可写计算可观察不更新

代码:

<script type="text/javascript"> 

    var model = null; 

    function EditModel() { 

     this.Count = 2; 

     var self = this; 

     this.ExistingValue = ko.observable(""); 

     this.ValidText = ko.computed({ 
      read: function() { 
       return self.ExistingValue(); 
      }, 
      write: function (text) { 
       if (text.split(',').length === self.Count) { 
        self.ExistingValue(text); 
       } 
      }, 
      owner: self 
     }); 
    } 

    $(document).ready(function() { 

     model = new EditModel(); 

     model.ValidText('@(Model.Text)'); 

     ko.applyBindings(model); 
    }); 

</script> 

<div id="mainContainer"> 
    <div id="editor" contenteditable="true" class="commentEditBox" data-bind="text: ValidText, valueUpdate: 'afterkeydown'" ></div> 
</div> 

结束了自定义绑定的想法去和转换的代码如下:

<script type="text/javascript"> 

    var model = null; 

    ko.bindingHandlers.customEditorBinding = { 
     init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 

      $(element).on('keydown', function() { 
       var observable = valueAccessor(); 
       observable($(this).text()); 
      }); 
     }, 
     update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
      var text = ko.utils.unwrapObservable(valueAccessor()); 

      if (text.split(',').length === model.Count) { 
       model.ValidText(text); 
       model.PreviousText = text; 
       $(element).text(text); 
      } 
      else { 
       model.ValidText(model.PreviousText); 
       $(element).text(model.PreviousText); 
      } 
     } 
    }; 

    function EditModel() { 

     var self = this; 

     self.Count = 2; 

     self.ValidText = ko.observable(""); 

     self.PreviousText = null; 
    } 

    $(document).ready(function() { 

     model = new EditModel(); 

     model.ValidText('This is,a test'); 

     ko.applyBindings(model); 
    }); 

</script> 

<div id="mainContainer"> 
    <div id="editor" contenteditable="true" class="commentEditBox" data-bind="customEditorBinding:ValidText" ></div> 
</div> 

回答

1

好吧,混淆使用的自我,这分开,你已经绑定它使用文本到一个div,并且您正在尝试在值更改时更新它。这个HTML元素没有任何价值,所以这就是为什么它不会触发。

看看custom binding并将您的写入逻辑移到它的更新方法中。

ko.bindingHandlers.yourBindingName = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     // This will be called when the binding is first applied to an element 
     // Set up any initial state, event handlers, etc. here 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     // This will be called once when the binding is first applied to an element, 
     // and again whenever the associated observable changes value. 
     // Update the DOM element based on the supplied values here. 
    } 
}; 
+1

我同意它不一致,但它应该没关系。我更新了它,以使用它们,但仍然是相同的问题 – TGH 2013-03-08 16:10:23

+0

够公平的,但我总是首先寻找最简单的解释,并且不一致是开始的好地方!无论如何,试试这个答案。 – 2013-03-08 16:17:11

+0

好吧,酷我得到它的工作。感谢 – TGH 2013-03-08 17:14:50

0

在你写方法,添加此else子句:

else { self.ValidText.notifySubscribers(self.ExistingValue()); } 

这将迫使文本框更新回原来的值。

+0

的想法问题是,我不能让它着火。尝试添加其他的,但它从来没有达到这种条件,因为它只在有效时才开始发射 – TGH 2013-03-08 16:09:02