2016-07-31 34 views
0

我有問題讓我的搜索工作。我希望能夠在輸入名字搜索後更新原始列表。使用ASP.Net搜索Knockout.Js

我的JavaScript

var ViewModel = function() { 
    var self = this; 
    self.police = ko.observableArray(); 
    self.error = ko.observable(); 
    self.detail = ko.observable(); 


    var policeUri = '/api/polices/'; 

    self.getPoliceDetail = function(item) { 
    ajaxHelper(policeUri + item.Id, 'GET').done(function(data) { 
     self.detail(data); 
    }); 
    } 

    function ajaxHelper(uri, method, data) { 
    self.error(''); // Clear error message 
    return $.ajax({ 
     type: method, 
     url: uri, 
     dataType: 'json', 
     contentType: 'application/json', 
     data: data ? JSON.stringify(data) : null 
    }).fail(function(jqXHR, textStatus, errorThrown) { 
     self.error(errorThrown); 
    }); 
    } 

    function getAllPolices() { 
    ajaxHelper(policeUri, 'GET').done(function(data) { 
     self.police(data); 
    }); 
    } 

    // Fetch the initial data. 
    getAllPolices(); 
}; 

ko.applyBindings(new ViewModel()); 

我的搜索框HTML。我有一個簡單的數據綁定就像這樣爲我的HTML。

<ul class="list-unstyled" data-bind="foreach: police"> 
    <li> 
    <strong><span data-bind="text: FirstName"></span> <span data-bind="text: LastName"></span></strong> : <span data-bind="text: Gender"></span> 

    <input type="search" class="form-control" data-bind="textInput: query" autocomplete="off" /> 
+0

你想讓搜索框工作在客戶端或服務器端嗎?你已經嘗試了什麼?你的數據是什麼樣的? – user3297291

+0

我希望它能夠像客戶端的實時更新一樣工作。我將我的數據綁定到了可觀察的淘汰賽,但沒有過濾數據。一旦我打電話給getallpolice,如果一個人要搜索警察,我只想過濾這些結果並更新視圖。 –

回答

0

首先,你必須添加query屬性你必然要搜索輸入您的視圖模型:

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

現在,你可以做一個computed屬性,訂閱的變化police陣列,query可觀察。 Knockout管理你的依賴關係:如果你在一個計算器的方法中評估一個observable,它確保它始終是最新的!

self.filteredPolice = ko.pureComputed(function() { 
    var searchQuery = self.query(); 
    var currentPolice = self.police(); 
    var filteredPolice = []; 

    // TODO: filter the actual results 

    return filteredPolice; 

}); 

從你的HTML代碼段,我看到police的對象有一個FirstNameLastNameGender財產。我可以想象你想要在名字和姓氏中搜索。讓我們填寫// TODO

for (var i = 0; i < currentPolice.length; i += 1) { 
    var current = currentPolice[i]; 
    if (current.FirstName.indexOf(searchQuery) !== -1 || 
     current.LastName.indexOf(searchQuery) !== -1) { 
    filteredPolice.push(current); 
    } 
}); 

現在,你必須確保你foreach計算陣列:

如果你想在最後只搜索x毫秒按鍵,你可以延長你的query

self.query = ko.observable().extend({ 
    rateLimit: { 
    timeout: 200, 
    method: "notifyWhenChangesStop" 
    } 
}); 

我建議你測試這段代碼,並確保你理解它。然後,我們可以做一些重構並進行一些改進(其中一些可能是個人偏好的問題)。

代碼以上的主要問題是,它不包括大多數的搜索可能性。此時,它尋找一個確切的匹配或者第一個,的姓氏。所以「John Doe」不會匹配{ FirstName: "John", LastName: "Doe" }。如果你不確定如何解決這個問題,我會建議在javascript中查找關於客戶端搜索的一些不同的問題。我試圖把重點放在這個答案中的「淘汰賽方法」。


獨立搜索邏輯

我建議創造某種效用函數或PersonViewModel.contains方法來包含搜索邏輯。或使其更加通用的,做這樣的事情:(注意,這是在ES2015)使用

// Note: Case insensitive & not optimized for performance 
var objContainsStringInProps = function(str, props, obj) { 
    var lowerStr = str.toLowerCase(); 
    return props 
    .some(key => { 
     var value = obj[key]; 
     return value && (typeof value) === "string" && 
     value.toLowerCase().includes(lowerStr); 
    }); 
}; 

在計算泛型方法:

你的計算則可以是:

self.filteredPolice = ko.pureComputed(() => { 
    // Create a new method in which only the `obj` param is required: 
    var policeItemSearchMethod = objContainsStringInProps 
    .bind(null, self.query(), ["FirstName", "LastName"]); 

    return self.police() 
    .filter(policeItemSearchMethod); 
});