ajax在KnockoutJS的自动完成搜索框中触发两次

时间:2014-01-30 09:28:13

标签: javascript knockout.js

我的例子中有一个客户名表。

用户可以开始输入他们的名字,并会显示现有客户列表。 然后,他们可以选择所需的名称,它将填写所有名称字段(第一个/中间/最后一个)

必须通过输入FirstName字段来触发搜索/下拉列表。

小提琴: http://jsfiddle.net/cc4V4/1/

HTML

<p><input type="text" placeholder="Start typing to search for a name" data-bind="value: FirstName, valueUpdate: 'keyup'" /></p>
<p><input type="text" data-bind="value: MiddleName" /></p>
<p><input type="text" data-bind="value: LastName" /></p>

<ul data-bind="foreach: Names, visible: ShowAjaxResults">
    <li data-bind="click: function() { selectName($data) }">
        <span data-bind="text: First"></span>
        <span data-bind="text: Middle"></span>
        <span data-bind="text: Last"></span>
    </li>
</ul>

使用Javascript /敲除

var model = function(){
    var self = this;
    self.Names = ko.observableArray([
            {First: "Joe", Middle: "Willikins", Last: "Bloggs"},
            {First: "Sam", Middle: "Silly", Last: "Smith"},
            {First: "Dog", Middle: "Zebra", Last: "Cat"}]);
    self.ShowAjaxResults = ko.observable(false);

    self.FirstName = ko.observable('').extend({ throttle: 500 });
    self.MiddleName = ko.observable('');
    self.LastName = ko.observable('');

    self.FirstName.subscribe(function(newValue) {
       if(newValue.length > 2) {
            //ajax call to fill Names starting with newValue
            self.ShowAjaxResults(true);
            console.log('ajax call: ' + newValue);
       }

    });

    self.selectName = function(data) {
        self.FirstName(data.First);   
        self.MiddleName(data.Middle);
        self.LastName(data.Last);
        self.ShowAjaxResults(false);
    }
}

ko.applyBindings(model());

这很好但问题当然是,当选择名称时,它会更新FirstName,然后FirstName.subscribe将关闭并再次执行ajax调用。

我尝试过玩一些东西,但我很难过。

如何在选择所需名称时再次停止ajax触发?

也许有办法说明观察结果是如何更新的?例如,只通过按键更新来激活ajax

2 个答案:

答案 0 :(得分:2)

您是否可以设置一个布尔值observable来标记何时触发订阅:

self.fireSubscription = ko.observable(true);

self.FirstName.subscribe(function(newValue) {
    if(newValue.length > 2 && self.fireSubscription()) {
       //ajax call to fill Names starting with newValue
        self.ShowAjaxResults(true);
        console.log('ajax call: ' + newValue);
    }           
});

self.selectName = function(data) {
    self.fireSubscription(false);  // prevent the subscription firing
    self.FirstName(data.First);   
    self.MiddleName(data.Middle);
    self.LastName(data.Last);
    self.ShowAjaxResults(false);
    self.fireSubscription(true);   // enable the subscription 
}

更新了小提琴:http://jsfiddle.net/cc4V4/21/

答案 1 :(得分:1)

您真的不希望subscribe更改FirstName,而是捕获keyPress事件,以便向用户显示名称建议。

试试这个:

<input type="text"
       placeholder="Start typing to search for a name"
       data-bind="value: FirstName, valueUpdate: 'keyup', event: { keyup: AutoComplete }" />

在你的ViewModel中:

var model = function(){
    var self = this;

    self.AutoComplete = function(data, event){
        var newValue = event.target.value;
        if(newValue.length > 2) {
            //ajax call to fill Names starting with newValue
            self.ShowAjaxResults(true);
            console.log('ajax call: ' + newValue);
       }
        return true;
    }    

    self.Names = ko.observableArray([
            {First: "Joe", Middle: "Willikins", Last: "Bloggs"},
            {First: "Sam", Middle: "Silly", Last: "Smith"},
            {First: "Dog", Middle: "Zebra", Last: "Cat"}]);
    self.ShowAjaxResults = ko.observable(false);

    self.FirstName = ko.observable('').extend({ throttle: 500 });
    self.MiddleName = ko.observable('');
    self.LastName = ko.observable('');

    self.selectName = function(data) {
        self.FirstName(data.First);   
        self.MiddleName(data.Middle);
        self.LastName(data.Last);
        self.ShowAjaxResults(false);
    }
}

ko.applyBindings(model());

请参阅小提琴:http://jsfiddle.net/cc4V4/20/