0

I'm not sure what I've done wrong this is how I've setup other factories to share data as far as I can see, but even though the array should be passed by reference and I don't overwrite the array so the reference isn't lost the template never loads with the data I can see coming down from the find all request. Can anyone see what it is that I have/haven't done to get this factory to work and shared between controllers?

I originally set this up not using a service so I know the data returned from the request does work with the view, and if you look at my stubs the data is there (and it looks the same), but the view never updates. If this is something other than a glaring error that I've missed and don't seem to understand I'd appreciate a quick comment as well since I assumed it was the fact objects/arrays are passed by reference that makes this all work.

Contacts Controller

// Stripped down for brevity...
(function () {

    'use strict';

    function ContactsController(ContactsFactory,
                                ContactsResource) {

        var vm = this;

        vm.contacts = ContactsFactory.get();

        vm.findAll = function () {

            ContactsResource
                .all()
                .then(function (response) {
                    ContactsFactory.add(response.contacts); // <-- an array of objects for example: [{id: 5, username: "Richard39", email: "Sanford.Marilyne@Gibson.org",…},…]
                });
        };

        vm.remove = function (contact, index) {

            ContactsResource
                .remove()
                .then(function (response) {
                    ContactsFactory.remove(index);
                });
        };

        function init() {
            vm.findAll();
        }

        init();
    }

    ContactsController.$inject = [
        'ContactsFactory',
        'ContactsResource'
    ];

    angular
        .module('app')
        .controller('ContactsController', ContactsController);

})();

Contacts Service

// Stripped down for brevity...
(function () {

    'use strict';

    function ContactsFactory() {

        var contacts = [];

        function get() {
            return contacts;
        }

        function add(contacts) {

            console.log(contacts) // <-- array of objects

            angular.forEach(contacts, function(contact) {

                console.log(contact) // <-- object
                contacts.list.push(contact);
            });

            console.log(contacts) // <-- objects pushed onto array [Object, Object, Object, Object, Object,…]

            // But no update in view, which worked with same resource 
            // request, prior to switching to factory to share between 
            // controllers
        }

        function remove(index) {
            contacts.splice(index, 1);
        }

        // ---
        // PUBLIC API.
        // ---

        return {
            get: get,
            add: add,
            remove: remove
        };
    }

    ContactsFactory.$inject = [];

    angular
        .module('app')
        .factory('ContactsFactory', ContactsFactory);

})();

UPDATE

Using @Rob's suggest makes this work, and I noticed if I added service.contacts as the return value to the getter it also works, and I verified contacts could be removed. So I'm still interested in knowing why this works versus just using an array for contacts like the examples above. Are arrays not passed by reference as I originally thought, and it's only objects? I'd just like to put a name to what I did wrong so it's memorable.

(function () {

    'use strict';

    function ContactsFactory() {

        var service = {
            contacts: []
        };

        function get() {
            return service.contacts;
        }

        function add(contacts) {
            angular.forEach(contacts, function(contact) {
                service.contacts.push(contact);
            });

            console.log(contacts);
        }

        function remove(index) {
            contacts.splice(index, 1);
        }

        return {
            contacts: service.contacts, // <-- Rob's suggestion
            get: get, // <-- this also works now as well
            add: add,
            remove: remove
        };
    }

    ContactsFactory.$inject = [];

    angular
        .module('app')
        .factory('ContactsFactory', ContactsFactory);

})();
mtpultz
  • 17,267
  • 22
  • 122
  • 201
  • 1
    From first glance, I would think you would have to tie the contacts var to your service like this: var service = { contacts: [] } and when you get your contacts from your api call, you would set service.contacts = response...etc and then in your controller set vm.contacts = ContactsFactory.contacts. – Rob Apr 08 '16 at 20:30
  • Hi @Rob, that worked and I updated my question just asking why it works when you wrap the variable in an object and then pass it back. Appears to work using get() when I return service.contacts as well. – mtpultz Apr 08 '16 at 21:03
  • 1
    You're binding the data to an object in the service, and returning that service for your controllers to use. Since it's bound and being watched, any changes to that object property is reflected in the controllers using it. If you just use var contacts, it's not bound to anything therefore it's not being watched by the little Angular ninjas :) – Rob Apr 08 '16 at 21:18
  • Haha awesome thanks @Rob. If you want the points I'll mark an answer with description by you as the correct answer. – mtpultz Apr 08 '16 at 21:20
  • Nah, thats fine. Glad it's working. Understanding two-way binding takes a little while. Kudo's on the code style by the way. You're off to a good start there. – Rob Apr 08 '16 at 21:33
  • Also, I updated your controller with a few small changes here: https://jsfiddle.net/z7adr7p5/ What you have works, but it could be shored up just a bit. Just a suggestion. – Rob Apr 08 '16 at 21:37

0 Answers0