1

I have observable array. I want to filter observable depending upon some text. I will select option button and depending upon it i need to filter observable array and bind to table. Here is my code till now. This is my view

<table>
<tbody data-bind="foreach: dataOne">
    <tr   >
        <td data-bind="text: id"></td><td >&nbsp;&nbsp;&nbsp;</td>
        <td data-bind="text: display"></td><td >&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;</td>

    </tr>
</tbody>

<table >
       <tr>
            <td><input name="optbtn" type="radio" value="All"/> All</td>
            <td><input name="optbtn" type="radio" value="Selected"/> Selected</td>
        </tr>

</table>

Here is my view model

 var data1 = [{
  name1: "one",
  id: 1,
display: "<temp>Is this employee</temp> required <val>in our company</val>"
}, {
name1: "two",
id: 2,
 display: "<temp>Is this bachelor</temp>required in our group"
}, {
name1: "three",
id: 3,
 display: "Test"

}];


var viewModel = {
dataOne: ko.observableArray(data1),

};


$("input[name='optbtn']").change(function (e) {
        debugger;
        var str = "<temp>";
        var stringFromArray = "";
        if ($(this).val() == "All") {
            alert("All");
        }
        else {
            ko.utils.arrayFirst(self.dataOne(), function (data) {
                debugger;
                stringFromArray = data.display();
                if (stringFromArray.indexOf(str) == 0) {
                    return data.display();
                }

            });
        }
    });


ko.applyBindings(viewModel);

If i select "Selected" option button then it should only return with text "<temp>in it. So it should return only 2 records.

How can i achieve this? When i load my page it will show all records and mark "All" button as selected. When i selected "Selected" then it must filter records.

Update

here is my Fiddle

4

1 回答 1

3

I would suggest that you should use the checked binding on your options instead of subscribing manually to the change event.

<input name="optbtn" type="radio" value="All" 
       data-bind="checked: selection" />All
 <input name="optbtn" type="radio" 
       data-bind="checked: selection" value="Selected" />Selected

And in your view model:

var viewModel = {
    dataOne: ko.observableArray(data1),
    selection: ko.observable("All")
};

Now that you have the current selection on your viewmodel you can add a ko.computed (see doc) which does the filtering (it will trigger each time your viewModel.selection changes):

viewModel.filteredData = ko.computed(function () {
    var str = "<temp>";
    if (viewModel.selection() == "All") return viewModel.dataOne();
    return ko.utils.arrayFilter(viewModel.dataOne(), function (data) {
        stringFromArray = data.display;
        if (stringFromArray.indexOf(str) == 0) {
            return true;
        }
    });
});

And use this filteredData in your foreach:

<tbody data-bind="foreach: filteredData">
    <tr>
        ...
    </tr>
 </tbody>

Demo JSFiddle.

Note: you need to use ko.utils.arrayFilter if you want to filter an array based on a criteria instead of ko.utils.arrayFirst which returns the first found item. And you need to return true/false from its second parameter function to signal whether an item should be included or not.

于 2013-08-09T14:17:58.103 回答