Kat
Kat

Reputation: 485

Get element by property in Angular Factory

When I select a project in my portfolio I have the route /portfolio/:workName. In my controller, I want to set $scope.work to whichever project I have selected based on the workName. Here's what I have so far:

app.factory('Works', function(){

var Works = {}

Works.projects =[
    {
        name : "ProjectOne",
        string : "stuff",
    {
        name : "ProjectTwo",
        string : "more stuff",
    },
    {
        name : "ProjectThree",
        string : "stuff",
    }
];  

Works.findByName = function(name) {
    Works.projects.forEach(function(work) { 
        if(work.name == name) {
            return work;
        }
    });
}
return Works;
})

app.controller("ProjectController", function ($scope, Works, $routeParams) {
$scope.work = Works.findByName($routeParams.workName);
});

However, in the debugger, despite $routeParams.workName returns "ProjectOne", Works.findByName($routeParams.workName) returns undefined.

Upvotes: 0

Views: 140

Answers (3)

Ved
Ved

Reputation: 12113

These are the mistakes in your code:

  1. '{' missing in Works.projects.
  2. Use filter instead of forEach or map
  3. Your not returning the value properly. Correct way check in code snippet:

var Works = {};
Works.projects =[
    {
        name : "ProjectOne",
        string : "stuff"
    },
    {
        name : "ProjectTwo",
        string : "more stuff"
    },
    {
        name : "ProjectThree",
        string : "stuff"
    }
];  

Works.findByName = function(name) {
   //ES5 Syntax
   return  Works.projects.filter(function(work) { 
        if(work.name == name) {
            return work;
        }
    });
   
     //ES6 Syntax
    //return Works.projects.filter(work => (work.name == name));
}



console.log(Works.findByName('ProjectThree'))

Upvotes: 1

Stanislav Kvitash
Stanislav Kvitash

Reputation: 4622

The issue with you code is that forEach is not returning a value (you are not returning the result in findByName method and the return value of forEach is undefined as well), but simply executes a comparison. You can modify you method as following or use filter() method (Works.findByNameUsingFilter example):

angular.module('myApp', [])
.factory('Works', [function(){
    var Works = {};
    Works.projects = [
        {
            name: "ProjectOne",
            string: "stuff1"
        },
        {
            name : "ProjectTwo",
            string : "more stuff",
        },
        {
            name : "ProjectThree",
            string : "stuff",
        }
    ];

    Works.findByName = function(name) {
        var res = '';
        Works.projects.forEach(function(work) {
            if(work.name === name) {
                res = work;
            }
        });    
        return res;
    };
    
    Works.findByNameUsingFilter = function(name) {
        return Works.projects.filter(function(work) {
            return work.name === name;
        });    
    };

    return Works;
}])
.controller("ProjectController", ['$scope', 'Works', function ($scope, Works) {
    $scope.workUsingFindByName = Works.findByName("ProjectOne");
    $scope.workUsingFindByNameUsingFilter = Works.findByNameUsingFilter("ProjectThree");
}]);
<script src="//code.angularjs.org/1.6.2/angular.js"></script>

<div ng-app="myApp">
  <div ng-controller="ProjectController">   
  {{workUsingFindByName.string}}
  <br/>
  {{workUsingFindByNameUsingFilter[0]}}
  </div>
</div>

Upvotes: 2

Jesus Carrasco
Jesus Carrasco

Reputation: 1354

Check code an change Works.findByName to an a function without works.

app.factory('Works', function(){

var Works = {}

Works.projects =[
    {
        name : "ProjectOne",
        string : "stuff",
    {
        name : "ProjectTwo",
        string : "more stuff",
    },
    {
        name : "ProjectThree",
        string : "stuff",
    }
];  

var findByName = function(name) {
    Works.projects.forEach(function(work) { 
        if(work.name == name) {
            return work;
        }
    });
}
return {findByName: findByName};

});

app.controller("ProjectController", function ($scope, Works, $routeParams) {
$scope.work = Works.findByName($routeParams.workName);
});

Upvotes: 0

Related Questions