A191919
A191919

Reputation: 3462

share data between controllers angular js

Why $scope.items in First and Second controllers still have value First why it doesnot change to value From controller after invoking Load() function?

HomeController:

namespace MvcApplication6.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

        public JsonResult GetData()
        {
            string data = "From controller";
            return Json(data, JsonRequestBehavior.AllowGet);
        }
    }
}

Index.cshtml

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" rel="stylesheet" />

<script src="~/Scripts/jquery-1.9.1.min.js"></script>
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/MyScript/Custom.js"></script>
<script src="~/Scripts/angular-animate/angular-animate.min.js"></script>
<script src="~/Scripts/angular-ui/ui-bootstrap.min.js"></script>
<script src="~/Scripts/angular-ui/ui-bootstrap-tpls.min.js"></script>

<div ng-controller="LoadData" id="data">

</div>
<div ng-controller="First">
    {{items}}
</div>
<div ng-controller="Second">
    {{items}}
</div>
<script>
    $(document).ready(function () {
        angular.element(document.getElementById('data')).scope().Load();
    });
</script>

Custom.js

var app = angular.module('MyApp', ['ngAnimate',  'ui.bootstrap']);

app.controller('First', function ($scope, sharedProperties) {
    $scope.items = sharedProperties.getProperty();
    console.log("First controller",sharedProperties.getProperty());
});
app.controller('Second', function ($scope, sharedProperties) {
    $scope.items = sharedProperties.getProperty();
    console.log("Second controller", sharedProperties.getProperty());
});
app.controller('LoadData', function ($scope,$http, sharedProperties) {
    $scope.Load = function () {

        $http({ method: 'GET', url: '/Home/GetData' }).
   success(function (data, status, headers, config) {
       sharedProperties.setProperty(data);
       console.log('Loaded data',data);
   }).
   error(function (data, status, headers, config) {
       alert('error');
   });
}
}
);

app.service('sharedProperties', function () {
        var property = 'First';

        return {
            getProperty: function () {
                return property;
            },
            setProperty: function (value) {
                property = value;
            }
        };
    });

Upvotes: 0

Views: 138

Answers (2)

Alberto Venturini
Alberto Venturini

Reputation: 123

The problem is that, in both First and Second controllers, the variables $scope.items are initialized when the controllers are loaded. After that moment, they are not changed any more.

The order of execution here is as follows:

  1. controller 'First' is initialized, along with its variable $scope.items;
  2. controller 'Second' is initialized, along with its variable $scope.items;
  3. the callback from $http is called, but you never update the value of $scope.items on either controller.

As a possible solution, you can implement a simple callback mechanism (the standard observer pattern). For example:

app.service('sharedProperties', function () {
        var property = 'First';
        var callBacks = [];

        return {
            getProperty: function () {
                return property;
            },
            setProperty: function (value) {
                property = value;
                callBacks.forEach(function(callBack) { 
                  callBack(value);
                });
            },
            registerCallback: function(callBack) {
              callBacks.push(callBack);
            }            
        };
    }); 

Then you have your controllers register their callbacks:

app.controller('First', function ($scope, sharedProperties) {
    sharedProperties.registerCallback(function(data) {
      $scope.items = data;
    });

});

Alternatively you can use Angular events to communicate across controllers.

Upvotes: 1

MaKCbIMKo
MaKCbIMKo

Reputation: 2820

The reason is that you are working with strings. It means that when you calling:

$scope.items = sharedProperties.getProperty();

You're getting the copy of your string. To share the data between controllers, you can modify your controllers as following:

html:

...
<div ng-controller="First">
    {{items.getProperty()}}
</div>
...

js:

...
app.controller('First', function ($scope, sharedProperties) {
    $scope.items = sharedProperties;
});
...

or modify your service:

app.service('sharedProperties', function () {
        // having the 'object' property inside
        var property = {value:'First'};

        return {
            getProperty: function () {
                return property;
            },
            setProperty: function (value) {
                property.value = value;
            }
        }});

Both these solutions works because they're copying the reference to the object which contains the value instead of copying the value itself.

Upvotes: 0

Related Questions