-1

I have an array which I use to populate a table using ng-repeat. I am applying a filter in the controller, which filters the array based on the values of a certain variable columnFilter. Now, my table view isn't getting updating if I change that variable. I.e the filter isn't reapplying once the variable changes.

JS

var myApp = angular.module('myApp',[]);


function MyCtrl($scope, $filter) {
    $scope.name = 'Superhero';
    $scope.col={name:""};
    $scope.TableData = [{
      name: "2017/03/01-14",
      specification: "1wk",
    },
    {
      name: "2017/03/01-17",
      specification: "Set-04",
    },
    {
      name: "2017/03/04-11",
      specification: "1wk",
    },
    {
      name: "2017/04/01-14",
      specification: "1wk",
    },
    {
      name: "2017/03/10-10",
      specification: "Set-04",
    },
    {
      name: "2017/03/10-10",
      specification: "Set-04",
    }
    $scope.TableDataFiltered = $filter('filter')($scope.TableData, $scope.col);
}

HTML
<div ng-controller="MyCtrl">
<input type="text" ng-model="col.name">
<table>
<thead>
  <tr>
    <th>name</th>
    <th>spec</th>
  </tr>
</thead>
<tbody>
  <tr ng-repeat="item in TableDataFiltered">
    <td>{{item.name}}</td>
    <td>{{item.specification}}</td>
  </tr>
</tbody>
</table>
</div>

To all the answers telling how to use | filter: expression syntax, I know about that, but the actual app has other filters and such, which require the need to filter in the controller itself. (I provided a minimal example which doesn't make that point very clear, that's on me. )

ChaoticTwist
  • 544
  • 7
  • 25
  • _"the filter isn't reapplying"_ You chose to filter manually so you are responsible to apply the filter yourself whenever it's necessary. You mentioned that `$scope.$watch()` didn't work. What was the problem? – a better oliver Feb 21 '17 at 10:07
  • @zeroflagL There was no problem, it just did nothing. My table isn't updating when the filters are updated. I am checking the output of the filter variable to see if that is getting updated, and it is. The problem is that ng-repeat isn't refreshing for some reason. – ChaoticTwist Feb 21 '17 at 10:36

3 Answers3

1

When you use the filter from your html angular will watch the variables that it uses and re-evaluate the expression whenever it changes. If you want to call the filter from your code you will need to do the same:

var myApp = angular.module('myApp',[]);


function MyCtrl($scope, filterFilter) {
    $scope.name = 'Superhero';
    $scope.col={name:""};
    $scope.TableData = [...];

    $scope.$watch('col', function(newCol) {
        $scope.TableDataFiltered = filterFilter($scope.TableData, newCol);
    });
}

Note also that you can directly inject the filter you want to use, you don't have to look it up on the filter provider each time. From the docs:

For this, inject a dependency with the name <filterName>Filter into your controller/service/directive. E.g. a filter called number is injected by using the dependency numberFilter. The injected argument is a function that takes the value to format as first argument, and filter parameters starting with the second argument.

Note that if you're going to use the filter from the controller then you probably don't need to expose the unfiltered data in the $scope, in that case you could just make it an ordinary variable, or move the table data out of the controller into a service. That way you can avoid cluttering the controller (which should be controlling things) with data.

Duncan
  • 92,073
  • 11
  • 122
  • 156
  • Thank you for the detailed answer. I tried using the $scope.$watch() function but it didn't work. (I have a bad habit of using filter provider every time, will keep that in mind.:) ) – ChaoticTwist Feb 21 '17 at 09:21
  • 1
    also, I declared all the tabledata in my controller for the sake of making the code snippet shorter. In my actual program, the data is provided through a service. – ChaoticTwist Feb 21 '17 at 09:26
  • Please correct me , but as per my understanding angular calls a digest cycle for every change in scope variable. SO whenever you are changing "TableDataFiltered" it should trigger a digest cycle on the UI rendering. So may be the table data is not part of your controller so in that case you need to forcefully update your scope data . So that you get the updated data on the UI. This may help you [link] http://stackoverflow.com/questions/19744462/update-scope-value-when-service-data-is-changed – Yauza Feb 21 '17 at 10:00
0

No need to define $scope.TableDataFiltered in the controller, just use filter in your template:

<tr ng-repeat="item in TableDataFiltered | filter : col.name">

Mahmoud
  • 844
  • 1
  • 10
  • 17
0

You don't need to write a specific function for this, just use the inline synthax:

<tbody>
  <tr ng-repeat="item in TableDataFiltered | filter: col.name">
    <td>{{item.name}}</td>
    <td>{{item.specification}}</td>
  </tr>
</tbody>
Mistalis
  • 17,793
  • 13
  • 73
  • 97