简体   繁体   中英

How to filter through a table using ng-repeat checkboxes with Angularjs

Once upon a time this was working but somehow it's broken. I want to be able to produce checkboxes using ng-repeat to get as many checkboxes as required based on stored data and use these to filter through a table produced.

Additionally I don't want identical values for the checkboxes to be repeated.

I have made a plnkr with the code.

<div class="row">
    <label data-ng-repeat="x in projects">
        <input
        type="checkbox"
        data-ng-true-value="{{x.b}}"
        data-ng-false-value=''
        ng-model="quer[queryBy]" />
        {{x.b}}
    </label>
</div>

http://plnkr.co/edit/RBjSNweUskAtLUH3Ss6r?p=preview

So in summary.

  1. Checkboxes to filter Ref .

  2. Checkboxes to be unique.

  3. Checkboxes to be made based off ng-repeat using Ref .

ng-false-value directive needs a value set. Try ng-false-value='false' or ng-false-value='null' (in fact you can skip this one entirely if it has to just be a falsy value and not something concrete, like a string or certain number).

As you've pointed out in the comments, after selecting and then clearing the checkboxes, all rows are filtered out. It happens because unchecking the checkbox will set its value to false, and this does not agree with your entities' values (as you probably know, just stating it for others).

Therefore you do need to set this value to empty string in the end. That'd be the way:

$scope.$watch('quer.$', function () {
  if ($scope.quer.$ === false) {
    $scope.quer.$ = '';
  }
});

Okay, here's how to do it.

First, let's add a couple of lines of CSS in your to make sure all the checkboxes are visible:

<style>
  .row { margin-left: 0px }
  input[type=checkbox] { margin-left: 30px; }
</style>

Next, add the following lines to your controller:

app.filter('unique', function() {

  return function (arr, field) {
    var o = {}, i, l = arr.length, r = [];
    for(i=0; i<l;i+=1) {
      o[arr[i][field]] = arr[i];
    }
    for(i in o) {
      r.push(o[i]);
    }
    return r;
  };
})

  app.controller("maincontroller",function($scope){
    $scope.query = {};
    $scope.quer = {};
    $scope.queryBy = '$';
    $scope.isCollapsed = true;
    $scope.selectedRefs = [];

  $scope.myFilter = function (item) { 
    var idx = $scope.selectedRefs.indexOf(item.b);
    return idx != -1; 
  };

  $scope.toggleSelection = function toggleSelection(id) {
    var idx = $scope.selectedRefs.indexOf(id);
    if (idx > -1) {
      $scope.selectedRefs.splice(idx, 1);
    }
    else {
      $scope.selectedRefs.push(id);
    }
  };

Phew.

For some reason, your Plunkr's version of AngularJS didn't recognise the unique attribute, so I added one to your controller.

Finally, change your html to this:

<div class="row">
    <label data-ng-repeat="x in projects | unique:'b' | orderBy:'b'" >
        <input
        id="x.b"
        type="checkbox"
        ng-click="toggleSelection(x.b)"
        ng-init="selectedRefs.push(x.b)"
        ng-checked="selectedRefs.indexOf(x.b) > -1" />
        {{x.b}} 
    </label>
</div>

... and your ng-repeat to this...

<tr ng-click="isCollapsed = !isCollapsed" ng-repeat-start="x in projects | filter:myFilter | orderBy:orderProp">

If you're interested in knowing how this works, add these lines:

<div style="margin:10px 10px 30px 10px">
  <pre>{{ selectedRefs }} </pre>
</div>

I love this trick: you can see the exact contents of our " selectedRefs " array, and see it change as we tick/untick our checkboxes. This really helps when developing/testing our bindings!

捆绑

As you can see, these changes use the new unique function to get your list of distinct values from your project array, and when the page first loads, we push all of the values into our new " selectedRefs " array.

["123","321","456","654","789","987"] 

Then, as you tick/untick the checkboxes, we add/remove that item from this list.

Finally, we use that filter in the ng-repeat .

ng-repeat-start="x in projects | filter:myFilter | orderBy:orderProp"

Job done !

Update

If you wanted to start off with all checkboxes unticked , then it's a simple change. Just remove this line...

ng-init="selectedRefs.push(x.b)"

..and change the myFilter function to show all items initially..

$scope.myFilter = function (item) { 
    if ($scope.selectedRefs.length == 0)
        return true;

    var idx = $scope.selectedRefs.indexOf(item.b);
    return idx != -1; 
};

And to add a "Clear all" button, simply add a button to your form which calls a function in your AngularJS controller like this..

$scope.clearAll = function () { 
    $scope.selectedRefs = [];
};

(I haven't tested these suggestions though.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM