2

I am trying to share data between my controllers. I came from C# environment and I was accustomed to creating a class which contains a private member and some methods for retrieving and manipulating / storing data.

Here is a super simple example of what I have in mind

public class MyRepository
{
    private List<string> Items { get; set; }

    public MyRepository()
    {
        Items = new List<string>();
    }

    public List<string> Get()
    {
        return Items;
    }

    public string GetById(int Id)
    {
        return Items[Id];
    }

    public void AddItem(string sNewItem)
    {
        Items.Add(sNewItem);
    }

    public void DeleteItems()
    {
        Items.Clear();
    }

}

Now coming back to Angular, I did some research and found out that in order to be able to share data (to create the above mentioned repository) I have to create something called Service. Ok, no problem I followed a guide and came up with something like this:

angular.module("IP-APP", ["ngRoute"])
    .factory("Item", function () {
        var savedItem = {};

        function set(newItem) {
            savedItem = newItem;
        };

        function get() {
            return savedItem;
        };

        return {
            set: set,
            get: get
        };
    })

Which I can afterwards inject into my controllers. This works perfectly fine until I try to define my own method such as GetById. Suddenly Angular returns the .GetById is not a function

My question then is - Is it possible to create a repository in a way I have already mentioned (with the ability to define custom functions such as GetById)? If yes, how to do it properly?

Any help in this matter would be more than appreciated.

Robert J.
  • 2,631
  • 8
  • 32
  • 59

2 Answers2

1

After reading several posts I realized, that I was missing the final return statement. Here is how I managed to edit my code:

angular.module("IP-APP", ["ngRoute"])
    .factory("Items", function () {
        this.savedItems = [];

        function set(newItem) {
            this.savedItems = newItem;
        };

        function get() {
            return this.savedItems;
        };

        function GetById(id)
        {
            var returnedItem = {};
            angular.forEach(this.savedItems, function (value, key) {
                if (value.id == id)
                    returnedItem = value;
            });

            return returnedItem;
        }

        return {
            set: set,
            get: get,
            GetById: GetById
        };
    })

And then in my controller:

(function () {
    "use strict";

    angular.module("IP-APP").controller("detailController", detailController);

    function detailController ($routeParams, Item, Items) {
        var vm = this;
        vm.selectedItem = Items.GetById($routeParams.itemId);
    };
})();

Is this approach correct to addopt in my Angular Application?

Robert J.
  • 2,631
  • 8
  • 32
  • 59
1

Please see a possible solution using the service approach for sharing data across your angular project.

I've simulated setting your data, and return all or a specific item by id. See the code or the JSFiddle

View

<div ng-app="myApp">
 <div ng-controller="testCtrl">
    <b>Get all Service data</b><br/>
    <div ng-repeat="bot in data">
      {{bot.name}}   {{bot.id}}
    </div>
    <br/><br/>
    <b>Get 1 item with id from service</b><br/>
    {{bot.name}} - {{bot.id}}
  </div>
</div>

Controller & Service

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

// Service (singleton)
myApp.service('userService', function() {
    // data
  var savedItems = [];

  function setItem(newItem) {
    if(angular.isUndefined(newItem)) return;
    savedItems[newItem.id] = newItem;
  };

  function getAll() {
    return savedItems;
  };

  function getById(id) {
    if(angular.isUndefined(id)) return;
    return savedItems[id];
  };

  return {
    set: setItem,
    getAll: getAll,
    getById: getById
  };


});

// controller
myApp.controller("testCtrl", function($scope, userService) {
    // set data
  userService.set({'name' : 'bot1', 'id':1});
  userService.set({'name' : 'bot2', 'id':2});
  userService.set({'name' : 'bot3', 'id':3});
  userService.set({'name' : 'bot4', 'id':4});
    // get all
  $scope.data = userService.getAll();
  // get bot1 by id 1
  $scope.bot = userService.getById(1);
})

See Fiddle for demo

daan.desmedt
  • 3,752
  • 1
  • 19
  • 33
  • Thank you for your answer! What is the difference between your an mine solution? I use factory, whereas you use service – Robert J. Jul 29 '16 at 14:00
  • All Services are singletons; they get instantiated once per app. They can be of any type, whether it be a primitive, object literal, function, or even an instance of a custom type. The value, factory, service, constant, and provider methods are all providers. They teach the Injector how to instantiate the Services. Besides that difference, also note the way the `getById` differs. When using array you can use the key. Be sure to add correct handling if id does not exists. – daan.desmedt Jul 29 '16 at 14:02
  • Besides that, I did not see your updated answer yet since i was busy providing a solution to the problem you posted. Maybe it comes in handy :) – daan.desmedt Jul 29 '16 at 14:04
  • Thank you for your answers! :) – Robert J. Jul 29 '16 at 14:07