user3378165
user3378165

Reputation: 6916

Filter a table based on radio button selection

I have a table of users that I need to filter by their activity based on a radio button changed.

I did it with Knockout but it doesn't work, I don't get an error, but the table comes up empty, am I do something wrong?

Without the filtering, the page works perfectly (when the foreach is on users and not filteredUsers)

The radio buttons:

<div class="btn">
     <input id="active" checked class="filterOpt selectedRadio" name="filterOpt" type="radio" data-bind="checked: inactive, attr: { 'value': 'false' }" /> <label class="filterLbl selectedRadio" for="active">ACTIVE</label>
</div>
<div class="btn">
     <input id="inActive" class="filterOpt" name="filterOpt" type="radio"  data-bind="checked: inactive, attr: { 'value': 'true' }" /> <label class="filterLbl" for="inactive">INACTIVE</label>
</div>
<div class="btn">
     <input id="all" class="filterOpt" name="filterOpt" type="radio" data-bind="checked: inactive, attr: { 'value': 'all' }" /> <label class="filterLbl" for="all">ALL</label>
</div>

And the KO code:

self.users= ko.observableArray([]);
self.inactive = ko.observable();
self.filteredClients = ko.observableArray([]);

self.filteredUsers= ko.computed(function () {
    var val = self.inactive();
    return self.users().filter(function (item) {
        console.log(ko.toJSON(item));
        return item.inactive === val;
    });
});

Then my table:

    <!--ko foreach: filteredUsers-->
        <table class="table">
            <tr class="header">
                <td class="name n" data-bind="text: name"></td>
                <td class="rep" data-bind="text: email"></td>
                <td class="status" data-bind="text: inactive"></td>
            </tr>
        </table>

Upvotes: 1

Views: 756

Answers (2)

user3378165
user3378165

Reputation: 6916

After @JoseLuis's answer, I was able to get it to work with a few minor changes, I post it in case someone in the future will run into a similar issue.

As @JoseLuis mentioned the problem was with the comparison of Boolean and String, in order to solve that I parsed the String to Boolean then I got a comparison between two booleans.

And this is the entire function:

self.filteredUsers = ko.computed(function () {
    if (self.inactive() == "true" || self.inactive() == "false") {
        var val = JSON.parse(self.inactive());
    }
    else var val = self.inactive();
    return self.users().filter(function (item) {
        return (item.inactive() === val) || (val === 'all');
    });
});

Upvotes: 1

Jose Luis
Jose Luis

Reputation: 994

Your radio buttons returns the selected value as a string. If the User object has inactive as a boolean, then the === always is going to return false, because you are comparing a boolean with a string.

This is a Codepen as an example. You could see than User 2 has a true as a boolean, and is not show (User 1 is show).

This is the User object:

 function User(name, inactive){
    var self = this;
    self.inactive = inactive;
    self.name = name;
    self.email = "[email protected]"
  }

This is the ViewModel:

 function ViewModel() {
    self.users= ko.observableArray([
      new User('User 1', 'true'),
      new User('User 2', true),
      new User('User 3', 'false'),    
    ]);
    self.inactive = ko.observable();
    self.filteredClients = ko.observableArray([
    ]);

    self.filteredUsers= ko.computed(function () {
      var val = self.inactive();

      return self.users().filter(function (item) {
        console.log(ko.toJSON(item));
        return (item.inactive === val) || (val === 'all');
      });
    });
  }

As you can see, I create three User:

      new User('User 1', 'true'),
      new User('User 2', true),
      new User('User 3', 'false'),    

The second has true as boolean, the others have a string. If you change the boolean with a text, both users are shown.

Please, write you answer too.

:-)

Upvotes: 1

Related Questions