0

My index.html looks like this:

<div id="div1" ng-controller="StartMenu">
  <div id="button1" ng-click="doSomething()"></div>
  {{value}}
</div>
<div id="div2" ng-view></div>

Module configuration:

angular.module('app').config([$routeProvider, function($routeProvider) {
  $routeProvider.when('/start', {
    templateUrl: 'partials/start.html', controller: StartMenu
  });
}]);

start.html:

<div id="button2" ng-click="doSomething()"></div>
{{value}}

And controller function:

function StartMenu($scope, globals) {    // service globals defined elsewhere
  $scope.value = globals.value
  $scope.doSomething = function() {
    // Manipulate globals.value
    $scope.value = globals.value;
  }
}

The problem: These two div elements in index.html share a same controller function. When I click #button1 in #div1 doSomething is invoked and $scope.value is changed. The change is immediately rendered in #div1 and {{value}} changes but #div2 remains unchanged. How do I "force" #div2 to be rendered and to show the change in {{value}}?

Esa Toivola
  • 1,538
  • 3
  • 16
  • 27

2 Answers2

2

ng-view creates its own (child) scope, so the {{value}} in start.html is created on the child scope. This value property hides/shadows the property of the same name in the parent scope. There are a few possible solutions:

  1. use {{$parent.value}} in start.html
  2. use an object instead of a primitive on the parent $scope -- e.g., $scope.obj = {value: 2}. Then reference it in the child: {{obj.value}}. (Well, this won't work for your particular scenario, since value in the parent scope already references something else.)
  3. use a function in start.html: {{value()}} -- define that function on the parent scope.

For more info about scope inheritance, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

Update: I read the HTML too fast... div2 is not contained within div1. The issue is twofold:

  1. two controllers are being created, each of which creates its own value property on its own scope
  2. if globals.value is a primitive, then the controller scopes are getting copies of the values, not references.

Solutions 2 and 3 above apply here.
2 = Create an object on globals and reference a property of that object in the controller scopes (i.e., don't use a primitive).
3 = use a function in the controllers to access the global primitive value. Fiddles for both solutions are in the comments below.

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Thanks for your reply and reference to your detailed explanation elsewhere. I experimented with placing {{$id}} in #div1 and #div2 and indeed, they are different scopes. But referencing to $parent.value in start.html didn't work. Why should ng-view create a child scope to #div1's scope and not to $rootScope? – Esa Toivola Jan 14 '13 at 21:40
  • You're correct, div2 is not under div1, so div2's parent is likely the root scope -- I did not look at your HTML carefully enough, sorry. $parent won't work here (as you already discovered). I'm pretty sure your problem is that you are actually creating two StartMenu controllers -- one via ng-controller, and the other via ng-View. (Unlike services, which are singleton's, controllers are not singletons.) Each of these controllers has its own scope. So div2 creates a "value" property on its scope, which is different from the "value" property created on div1's scope. – Mark Rajcok Jan 14 '13 at 22:12
  • 1
    One way to fix the problem is to define a "value()" function in the controller that returns the value from the service. Here's a fiddle: http://jsfiddle.net/mrajcok/JduB9/. Every $digest cycle, the value() function will be evaluated, once for each controller. – Mark Rajcok Jan 14 '13 at 22:23
  • 1
    Another fix is to use an object in the service, rather than a primitive. This way, the controllers don't create a copy of the value in their scopes, rather, they get a reference. Fiddle: http://jsfiddle.net/mrajcok/JduB9/2/ – Mark Rajcok Jan 14 '13 at 22:32
  • If $scope.value is now a reference to globals.value, will $scope.value.value += 10 actually increment globals.value.value? – Esa Toivola Jan 14 '13 at 22:39
  • I solved my problem by defining a value() function. Also understood when a new scope is created. Thanks for your help! – Esa Toivola Jan 15 '13 at 19:23
0

In this case you can pass the value to service and get it from service

    // controller
    yourservicename.yourfunction = 'somthing text';

    $scope.getvalue = function() {

        return yourservicename.yourfunction;
    }

     // view

    <div ng-controller="myCtrl" > {{getvalue()}} </div>
    <div ng-controller="myCtrl" > {{getvalue()}} </div>