1

Here is a fiddle: http://jsfiddle.net/a0eLhcbm/

I have a simple setup:

<div ng-app="demo" ng-controller="PageController">

    {{ page.time }}

    <div ng-controller="UsernameController">
        {{ user.name }}
    </div>

</div>

There is a function that will, say, get the user.name from somewhere else using ajax, and that function belongs to controller PageController.

Question: Is there anyway I can make the {{ user.name }} within the UsernameController to update itself as soon as the controller PageController receives the information?

Here is my javascript setup:

var app = angular.module( 'demo', [] );

function_that_fetches_for_username = function() {
    //Some function that fetch for username asynchronously
};

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

    //Initial data
    $scope.page = {};
    $scope.page.time = Date();
    function_that_fetches_for_username();
    //How can I make the UsernameController to update its view from this Controller as soon as this controller receives the information?

});

app.controller( 'UsernameController', function( $scope ) {
    //Initial data
    $scope.user = {};
    $scope.user.name = "";

    //How can I automatically updated the $scope.user.name in view as soon as the PageController receives the information about the username?

});
cuzmAZN
  • 377
  • 1
  • 7
  • 25

3 Answers3

1

you can define your user in pageController(that is parent controller to UsernameController) now whenever you change it in pageController it will also be updated in usernameController

second solution is to have ng-view in parent, and in route use controller for UsernameController

index file

<div ng-app="demo" ng-controller="PageController">

{{ page.time }}
  <ng-view></ng-view>


  </div> 

user.html

 <div ng-controller="UsernameController">
    {{ user.name }}
   </div>

route codee

  .when("/user",{
  controller:"usernameController",
  templateUrl : 'user.html'

 })

Third solution is to make a service

.factory("userFactory",function(){
 var user = {};
 return{
 setUser : function(usern){
 user  = usern;

  },
 getUser : function(usern){
 return user;

},

 } 

}) now you can get user from service and set to service .

A.B
  • 20,110
  • 3
  • 37
  • 71
  • Who says PageController is parent of UsernameController?! – RaviH Oct 26 '14 at 07:22
  • see his Do tree and comtroller strcture, pageController is parent of UsernameController – A.B Oct 26 '14 at 07:24
  • Agreed. Sorry for overlooking it! – RaviH Oct 26 '14 at 07:29
  • Hi there. That I have thought of, but the thing is I cannot do that. I use routing to route to different page, there for I cannot bind the data to the root-est controller, because the data needs to be changed each time a new view is loaded. I used `` inside the UsernameController. – cuzmAZN Oct 26 '14 at 07:31
  • why not make a in main index file inside that tag of pageController, and if you preffer service i can edit my answer? – A.B Oct 26 '14 at 07:35
  • Please @AbdulBasit, it would definitely help me a lot! With a simple example code is good too! But can you look at this: http://jsfiddle.net/VxafF/. Even on this fiddle, we have to actually do something (in this case, ng-click) to update the view. I'd like it to be magically bound, just like what Angularjs does. – cuzmAZN Oct 26 '14 at 07:41
1

You can do one of these for sharing the same value through multiple controllers:

  1. Promote the value to a higher level scope all the interested controllers have access to. Controllers will get it through scope inheritance because angular automatically searches the value through the scope hierarchy.

  2. Whoever gets the value broadcasts it through the higher level scope all the controllers have access to. All the controllers listening for this broadcast will get the value.

RaviH
  • 3,544
  • 2
  • 15
  • 14
  • Hi! Can you please help me with the layout of the code? Just the basic one is very much appreciated!! – cuzmAZN Oct 26 '14 at 07:29
  • And one more thing, I am in the situation where I cannot (because it will break my page's logic) promote the value to the highest scope. I'd like it to be bound by the UsernameController's scope alone. – cuzmAZN Oct 26 '14 at 07:33
  • Hi @isim! I tried to use services, but in order to make the view automatically synced, I need to make my own loop setInterval() to fetch the data from PageController each time. I am wondering if there is any better solution – cuzmAZN Oct 26 '14 at 07:35
  • @cuzmAZN Use broadcast if you cannot promote the value to a higher scope. – RaviH Oct 26 '14 at 08:07
1

There are probably a lot of ways to solve this problem, my share to this is to use either of the two below:

[1] Create a service that you can share to any part of your application (Controllers, Services, Directives, and Filters).

In relation to your problem, you can simply create a User service that can be shared across your controllers. The solution below assumes that the function_that_fetches_for_username() is a service UserResource that has a method get() that simulates fetching data from a server. The User service is an empty object that is shared across all your controllers.

DEMO

JAVASCRIPT

angular.module('demo', [])

  .service('UserResource', function($timeout) {
    this.get = function() {
      return $timeout(function() {
        return {
          id: 'w3g45w34g5w34g5w34g5w3',
          name: 'Ryan'
        };
      }, 2000);
    };
  })

  .service('User', function() {
    return {};
  })

  .controller('PageController', function($scope, UserResource, User) {

    $scope.page = {
      time: Date()
    };

    UserResource.get().then(function(data) {
      angular.extend(User, data);
    });
  })

  .controller('UsernameController', function($scope, User) {
    $scope.user = User;
  });

HTML

<div ng-app="demo" ng-controller="PageController">

  {{ page.time }}
  <hr>

  <div ng-controller="UsernameController">
      <div ng-if="user.name">
        {{ user.name }}
      </div>
      <div ng-if="!user.name" style="color: red">
        Waiting for Response...
      </div>
  </div>

</div>

[2] Use the controllerAs syntax for declaring controllers. Use this type of notation for child controllers to access parent controllers using their aliases.

DEMO

JAVASCRIPT

angular.module('demo', [])

  .service('UserResource', function($timeout) {
    this.get = function() {
      return $timeout(function() {
        return {
          id: 'w3g45w34g5w34g5w34g5w3',
          name: 'Ryan'
        };
      }, 2000);
    };
  })

  .controller('PageController', function(UserResource) {
    var ctrl = this;

    ctrl.page = {
      time: Date()
    };

    ctrl.user = {};

    UserResource.get().then(function(data) {
      angular.extend(ctrl.user, data);
    });

  })

  .controller('UsernameController', function() {
    this.getUser = function(user) {
      console.log(user);
    };
  });

HTML

<div ng-app="demo" ng-controller="PageController as PC">

  {{ PC.page.time }}
  <hr>

  <div ng-controller="UsernameController as UC">

      <div ng-if="PC.user.name">
        {{ PC.user.name }}
      </div>

      <div ng-if="!PC.user.name" style="color: red">
        Waiting for Response...
      </div>

      <button type="button" ng-click="UC.getUser(PC.user)"
        ng-disabled="!PC.user.name">
        Access user from Page Controller
      </button>

  </div>

</div>
ryeballar
  • 29,658
  • 10
  • 65
  • 74
  • Note that you can also declare your route controllers with an alias using the [**`controllerAs`**](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider#when) route object property. – ryeballar Oct 27 '14 at 07:00