将input元素的值作为参数传递给viewmodel函数

时间:2016-05-15 20:22:18

标签: knockout.js

input控件value传递给viewmodel函数的语法是什么(假设有一个)?在我的场景中,我对将输入的值绑定到viewmodel上的属性不感兴趣。我只需要对输入控件中输入的值进行操作(基本上我会迭代一组项目并过滤掉那些不包含输入文本的项目。)

<input data-bind="text: filterText($data), valueUpdate: 'afterkeydown'">

我已尝试filterText($data, value)但Knockout正试图在viewmodel上找到value属性。我实际上需要来自输入控件的当前值。

这可能吗?

4 个答案:

答案 0 :(得分:4)

处理此用例的典型方法是对调用filterText的绑定值使用textInput绑定和订阅。

<input data-bind="textInput: filter">

在你的剧本中:

filter.subscribe(function(newValue) {
    filterText(newValue)
});

你可以简化为:

filter.subscribe(filterText);

但是你仍然可能在考虑这个错误。您的筛选列表应该是一个计算引用textInput绑定filter值以计算筛选列表。

filteredList = ko.pureComputed(function() {
    // return the list filtered by the bound filter() value
}, self);

然后,您可以在需要过滤的数据列表的任何地方使用filteredList()

答案 1 :(得分:1)

首先要做的事情。您的示例代码在input节点上使用a text binding,这不是那么有用(它意味着从视图模型到DOM的单向绑定,“文本“那个没有意义的input的内容。鉴于valueUpdate绑定存在,您可能意味着the value binding?请注意the textInput binding是在现代版本的KnockoutJS中将这两者结合起来的方式。

至于你的实际问题,缺少重要的背景:为什么你(想你)想要这样做?根据具体情况,解决方案会有所不同,或者您甚至可能会得到XY-problem

无论如何,要回答。

选项1
尽管如此,我试图回答具体问题,我在你的观察点上写.subscribe作为一种可能的解决方案的第二@JohnnyHK's answer

选项2
另一个可能的解决方案非常类似于那个,但试图满足“我对输入的值”部分不感兴趣,我建议使用只读计算的observable:

function Root() {
  var self = this;
  
  self.filter = ko.computed({
    read: function() { return ""; }, // <-- not recommended, read context!
    write: function(newValue) {
      // You're free to discard the newValue   <-- not recommended, read context!
      alert("Input has been changed.");
    }
  });
}

ko.applyBindings(new Root());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<input data-bind="textInput: filter">

现在这显然丢弃了写位中的newValue(根据您的请求),因此也有一个奇怪的read函数。 我不建议使用,而是建议使用带有后备observable的私有变量进行读写。但实际上,这将使该选项等同于另一个答案中的第一个选项。

一个有趣的说明,你的问题是关于“收集”和过滤输入:如果你看the docs from writeable computeds你会发现接受用户输入或不满足某个条件是< / em>实际上是一个用例。

选项3
我建议使用,如果我稍微改写一下你的请求:

  

当您的操作不关心实际的input时,您如何对惯用的KnockoutJS进行value value更改做出反应?

为了编写与DOM的自定义交互,有custom binding handlers。你可以有一个根本不使用ViewModel的,或者有一个可观察的。(/ p>

选项3.A

ko.bindingHandlers["opacitor"] = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    $(element).on("keydown", function() {
      $(this).animate({ opacity: 0.05 }, 1000, function() { $(this).animate({ opacity: 1.0 }, 1000); });
    });
  }
}

ko.applyBindings({});
input { background-color: gold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<input data-bind="opacitor">

选项3.B
或者使用视图模型的第二个选项:

ko.bindingHandlers["opacitor"] = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    $(element).on("keydown", function() {
      var speed = ko.utils.unwrapObservable(valueAccessor)();
      $(this).animate({ opacity: 0.05 }, speed, function() { $(this).animate({ opacity: 1.0 }, speed); });
    });
  }
}

// speed1 and speed2 could also be observables
ko.applyBindings({ speed1: 500, speed2: 2000 });
input { background-color: gold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<input data-bind="opacitor: speed1">
<input data-bind="opacitor: speed2">

选项3A和3B的缺点是您需要编写自定义事件处理逻辑。如果你看一眼the textInput source from KO,你会发现它是非常简单来正确地跨浏览器处理这些事情。所以使用选项1或2可能仍然会更好(即使你有一些视图模型交互,即使“你不感兴趣”)。

选项4
使用the event binding。这与选项3具有相同的缺点,但仍然可能是一个简单的解决方案。这是一个例子:

function Root(){
  var self = this;
  self.myFn = function(data, element) {
    console.log(element.target.value);
    return true;
  };
}

ko.applyBindings(new Root());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<input data-bind="event: { keyup: myFn }">

您将在最后一个中看到一个微妙的变化,以及我想要结束的一个问题:您实际上没有this issue,您实际上需要 new 值因此不应该看afterkeydown而是看一个不同的事件?

答案 2 :(得分:1)

使用$ element.value访问输入值。

答案 3 :(得分:0)

如果您没有将属性绑定到视图模型,那么您可以使用jquery / javascript直接在视图模型函数中获取该输入控件的值,方法是这样做。

self.Filter= function () {           
   var filter = $('#textBoxID').val();
   //    
}

这样您就不需要将值传递给view-model函数参数。