Search code examples
angularjsangularjs-directiveangularjs-ng-repeatangularjs-filterangularjs-factory

Get object context in angularJs filter method?


I'm completely stumped. I'm not understanding why I'm getting the parent scope on the object in my plunker (Line 51).

As far as I can tell, it looks like Angular must be calling .call() or .apply() on the filter, setting it's context to the current $scope or something. But that just seems odd, why not just call the method and leave the context alone?

angular.module('MyApp', [])
.controller('MyCtl', function(
  $scope,
  WidgetsService
){
  WidgetsService.getWidgets().then(function(widgets){
    $scope.entireWidgetsList = widgets;
  });

})
.directive('widgetsFilteredList', function(
  WidgetsService
){
  return{
    restrict: 'E',
    scope: {
      filter: '='
    },
    templateUrl: 'widgets-filtered-list.directive.html',
    controller: function($scope){
      $scope.typeAheadModel = null;
      $scope.widgetsResults = null;
      $scope.$watch(function(){
        return ($scope.typeAheadModel) ? $scope.typeAheadModel : null;
      }, function(newV, oldV){
        if(newV && newV != oldV){
          var reqPromise = WidgetsService.getWidgets();

          reqPromise.then(function(widgets){
            $scope.widgetsResults = widgets;
          }, angular.noop);
        }
      });
    }
  };
})
.factory('WidgetFactory', function(){
  function Widget(data){
    var defaultStructure = {
      id: null,
      color: null,
      cogs: []
    };

    _.merge(this, defaultStructure, data);
  }

  Widget.prototype.widgetFilter = function(){
    var self = this;
    return function(widget){
      console.log(self); //How the heck do I get this to give me the proper context??
      //compare 'widget' this the widget in context for return value.  Like:
      // return !!!(widget.id === self.id);  //Would remove the context widget from the result set;
      return true;
    }
  };

  var create = function(data){
    return new Widget(data);
  };

  return {
    create: create
  };
})
.service('WidgetsService', function(
  WidgetFactory,
  $q,
  $timeout
){
  return {
    getWidgets: function(){
      var def = $q.defer();

      $timeout(function(){
          var widgetResults = [
            WidgetFactory.create({
              id:1,
              color: 'red',
              cogs: []
            }),
            WidgetFactory.create({
              id:2,
              color: 'blue',
              cogs: [1, 2]
            }),
            WidgetFactory.create({
              id:3,
              color: 'green',
              cogs: []
            }),
            WidgetFactory.create({
              id:4,
              color: 'yellow',
              cogs: []
            })
          ];

          def.resolve(widgetResults);
      }, 500);

      return def.promise;
    }  
  };
});

Solution

  • You are passing your widgetFilter as a closure, essentially to $scope, thats why you see the console.log(self) output being the $scope object. Instead put the widgetfilter function inside the factory like this:

    .factory('WidgetFactory', function(){
      function Widget(data){
        var defaultStructure = {
          id: null,
          color: null,
          cogs: []
        };
    
        var self=this
        this.widgetFilter=function(){
          console.log(self)
        }
    
        _.merge(this, defaultStructure, data);
      }