1

I need to pass bunch of variables to a filter, so I figured it'd be easier to pass the whole model, since it's just a reference anyway. So I tried to do this (this is a simplified version):

app.filter('applyLimit', function() {
  return function(files, m) {
    return files.map(function(v,i){
        v.analyze = i < m.limit
      return v
    })
  }
});

angular.module("app").component("h2jcomponent", {
    templateUrl: "html/View.html",
    controllerAs: "m",
    controller: ['$filter', H2J_Controller]
});

function H2J_Controller($filter) {
    var m = this
    m.limit = 1
    var files = [{name:'foo.java',analyze:true},{name:'bar.java',analyze:true}]
    $filter('applyLimit')(files,m)
}

However I'm getting the following error:

TypeError: Cannot read property 'limit' of undefined

I'm assuming this is because I can't pass my entire model to a filter, but I'm not sure. Is this possible?

Travis Heeter
  • 13,002
  • 13
  • 87
  • 129
  • 1
    please try to replicate your problem on this plunker: https://plnkr.co/edit/0TYC56eNLSugPp8tDFeH?p=preview – Andriy Nov 04 '16 at 21:38
  • 1
    yes i am also not getting TypeError: Cannot read property 'limit' of undefined – user3249448 Nov 04 '16 at 21:48
  • Near possible solution is [here](http://stackoverflow.com/a/17813797/4593781) – Muhammad Faizan Uddin Nov 04 '16 at 22:33
  • @Andriy Sorry, didn't realize I didn't put `files` in as a param. https://plnkr.co/edit/el6yb3xRnkw4sku1kjEm?p=preview. That shows the issue, I've also edited my question. Also, because of this comment I was able to figure out the issue, I posted an answer, but if you want to post it, I'll delete mine and give you credit. – Travis Heeter Nov 07 '16 at 14:23

2 Answers2

1

first filter's argument should be processed array (files in our case) and then after it any optional additional arguments (limit in our case). This way, our filter may be used in HTML with directives like ng-repeat (ng-repeat="file in vm.files | vm.applyLimit : vm") or just angular expression within curly braces like

<pre>{{ vm.files2 | applyLimit : vm | json }}</pre>

so I rewrote filter to:

app.filter('applyLimit', function() {
  return function(files, scope) {
    return files.map(function(v, i){
      v.analyze = i < scope.limit;
      return v;
    })
  }
});

updated plunker: https://plnkr.co/edit/0TYC56eNLSugPp8tDFeH?p=preview

Andriy
  • 14,781
  • 4
  • 46
  • 50
  • I want to pass in the model, not just limit (even though that's all it needs in this example). Why does it not work when I pass (files, m), and it does work when I pass (m,files)? – Travis Heeter Nov 07 '16 at 21:09
  • 1
    your plunker (https://plnkr.co/edit/el6yb3xRnkw4sku1kjEm?p=preview) works just fine, just add `m.files = angular.copy(files);` in your app.js (line 13 for example). It works when you pass (files, m). I updated my plunker and answer to receive model and not just limit – Andriy Nov 07 '16 at 21:51
0

I'm not sure why, but changing the order of the params fixed it:

app.filter('applyLimit', function() {
  return function(m, files) {           // <---- changed from (files,m) to (m,files)
    return files.map(function(v,i){
        v.analyze = i < m.limit
      return v
    })
  }
});

angular.module("app").component("h2jcomponent", {
    templateUrl: "html/View.html",
    controllerAs: "m",
    controller: ['$filter', H2J_Controller]
});

function H2J_Controller($filter) {
    var m = this
    m.limit = 1
    var files = [{name:'foo.java',analyze:true},{name:'bar.java',analyze:true}]
    $filter('applyLimit')(m,files)      // <---- also here
}
Travis Heeter
  • 13,002
  • 13
  • 87
  • 129