Search code examples
javascriptangularjsangularjs-controllerangularjs-model

AngularJS - Using Model in Controller causing Model to update


I have an Angular application where in I'm pulling from a model some data which is saved on the load of the app. For simplicity sake, I've explicitly defined the data which is being pulled.

The issue I have is that in one of my controllers I am running a function on load of the controller which modifies the data pulled from the model. The point is that I want that extra data for that page which is using that controller only. I don't want that data to be saved back into the model (which is what's happening).

My model:

'use strict';
(function () {
    var PotsMod = function ($log, _) {
        return {
            pots: [
                {"comp" : "comp1"},
                {"comp" : "comp2"}
            ],
            getPots: function () {
                return this.pots;
            },
        };
    };
    angular
        .module('picksApp.models')
        .factory('PotsMod', PotsMod);
})();

My controller:

(function () {
    function AdmCtrl($log, $routeParams, PotsMod) {
        var vm = this;
        vm.pots = PotsMod.getPots();
        vm.init = function() {
            // populate pot.competition
            _.forEach(vm.pots, function(pot) {
                pot.comp = "test";
            });
            console.log(PotsMod.getPots());
        }
        vm.init();
    }
    angular
        .module('picksApp.controllers')
        .controller('AdmCtrl', AdmCtrl);
})();

The final line in vm.init(), PotsMod.getPots(), returns to me the updated model, with the values of "comp" as test.

So I tried this instead - I put the debug line under vm.pots like so:

    var vm = this;
    vm.pots = PotsMod.getPots();
    console.log(vm.pots);
    vm.init = function() {....

This also returns to me the array where the object values are test...

So I tried one final thing and added an extra debug line in the vm.init() function too:

    var vm = this;
    vm.pots = PotsMod.getPots();
    console.log(vm.pots);
    vm.init = function() {
        // populate pot.competition
        _.forEach(vm.pots, function(pot) {
            console.log(pot.comp);
            pot.comp = "test";
        });
        console.log(PotsMod.getPots());
    }
    vm.init();

The result of this confuses me... The output in the console reads:

[{"comp":"test"},{"comp","test"}]
comp1
comp2
[{"comp":"test"},{"comp","test"}]

I must be missing something here because I don't understand how it can be defining a variable using a model's value, printing that variable with the updated values, then using the old values and printing them, then printing the updated values again from the model (even though nothing in this code touches the model).

Any help would be brilliant please, I see to be making a fundamental mistake somewhere. Thank you.


Solution

  • You're referencing the service's pots object in your controller, so your controller code is also modifying the service's code.

    I created a Plunker to demonstrate how angular.copy() creates a deep copy of your service's 'pots', and thus your controller's model is no longer referencing the original.

    In your case, all you need to change is vm.pots = angular.copy(getPots());

    http://plnkr.co/edit/jg5mWIWds1KMJd51e3o5?p=preview