user3099838
user3099838

Reputation:

AngularJS. Using values/scopes from different controllers throughout the application

I understand that using $rootScope to share values between controllers is a bad idea and everybody recommends using Services and as an answer links to the the angular docs. However I am at loss there, because the official documentation does not show any simple example, and when I tried to implement some examples from here, StackOverflow – they did not work for me (maybe because I am using ng-repeat?). I have been trying to solve it for several days, as to not to bother you here, but now I am at totally at loss.

Could you please show me how to solve the example below, and I will then use it in my application (where I have about 50 different scopes used in 5 different controllers). The example below is the simple outline of my problem. I have also created a plunker for it http://plnkr.co/edit/J4fZ51koueyUX9mXqzDk?p=preview

I have three controllers in my JS:

app.controller('TotalCalc', function($scope) {

  });

app.controller('color', function($scope) {
  $scope.colors = [
  {name1: "Red",price1: 300},
  {name1: "Green",price1: 660},
  {name1: "Black",price1: 920}
];});

app.controller('coating', function($scope) {
  $scope.coatings = [
  {name2: "Single coating",price2: 2},
  {name2: "Double coatings",price2: 4},
  {name2: "Triple coating",price2: 7}
];});

And in my HTML I have:

<div class="container" ng-controller="TotalCalc">
Here I want to calculate a value: (color selected price) * (coating multiplier)<br>
Using the "selected.price1" * "selected.price2", from the "color" and "coating" controllers below.

<div class="col-xs-6" ng-controller="color">
<strong>Color selected price: {{selected.price1 ||0}}</strong>
 <div class="list-group small">
  <a ng-repeat="color in colors" ng-click="$parent.selected = color" class="list-group-item" ng-class="{active:selected==color}"><span class="badge pull-right">$ {{color.price1}}</span>{{color.name1}}</a>
 </div>
</div>

<div class="col-xs-6" ng-controller="coating">
 <strong>Coating multiplier: {{selected.price2 ||0}}</strong>
 <div class="list-group small">
  <a ng-repeat="coating in coatings" ng-click="$parent.selected = coating" class="list-group-item" ng-class="{active:selected==coating}"><span class="badge pull-right">{{coating.price2}}</span>{{coating.name2}}</a>
 </div>
</div>
</div>

See, that whole place (single-page-application) is under the "TotalCalc" controller and from there I cannot access the values from the other two controllers inside it.

I understand that I should use the Service(?) somehow, if I want to access any values/scopes from the different controllers throughout the whole application. But after several days reading up and trying, I cannnot find a way for it to work. :( Can you please use my simplified example above, and to show me how it is done? Thank you in advance.

Upvotes: 0

Views: 210

Answers (1)

charlietfl
charlietfl

Reputation: 171669

As @Nikos pointed out, you really don't need multiple nested controllers here. That being said, here is an example of using a service as well as some custom events for communicating. The events aren't needed as you can bind all the data together through the service , but I put them in for inspiration

app.factory('CoatingService', function() {
  var thisService = {
    colors: [
      {name1: "Red",price1: 300},
      {name1: "Green",price1: 660},
      {name1: "Black",price1: 920}
    ],
    coatings: [
      {name2: "Single coating",price2: 2},
      {name2: "Double coatings",price2: 4},
      {name2: "Triple coating",price2: 7}
    ],

    selected:{
      color:{},
      coating:{}
    }
  }

  return thisService

})

app.controller('TotalCalc', function($scope, CoatingService) {
  $scope.selected=CoatingService.selected;
 function updateTotal(){
      $scope.totalprice= ($scope.selected.color.price1 ||0) + ($scope.selected.coating.price2||0)
 }
 updateTotal();

 $scope.$on('doPriceUpdate',function(){
   updateTotal();
  })

});

app.controller('color', function($scope, CoatingService) {

  $scope.colors = CoatingService.colors;
  $scope.selected = CoatingService.selected;

  $scope.updateColor=function(color){
    $scope.selected.color=color;
    $scope.$emit('doPriceUpdate')
  }  

});
/* similar pattern for coating controller*/

You could do this all within one controller though quite easily with less code but still keep the service to store data

DEMO

Upvotes: 1

Related Questions