1

Say I've got AdamController as adam and AnujController as anuj. I want anuj.anujProp to have a j appended to it every time adam.adamProp changes.

How could this be done? What is the best way?

Adam Zerner
  • 17,797
  • 15
  • 90
  • 156

1 Answers1

3

Here are 4 possible ways that I came up with. I ranked them in the order that I personally feel is best.

  1. Events - http://plnkr.co/edit/4AD8e47DaOSuutrphIkN?p=preview
  2. Method on a Factory - http://plnkr.co/edit/Vixab8LjDtow5YYfnlMV?p=preview
  3. Factory + $watch - http://plnkr.co/edit/1zVZ9EDarCGPOMZvrJMd?p=preview
  4. $scope inheritance - http://plnkr.co/edit/3b7tzPI5Y4CcwWYXUk25?p=preview

The $scope inheritance approach just feels "messy". I like the event driven approach over the factory approaches because I feel like there's a sort of overhead associated with the factories, and if it's only going to be used for this one purpose, the overhead isn't worth it. Plus, this just seems to be exactly what events are for. I put (2) ahead of (3) because the $watch hurts performance.


  1. Events

angular
  .module('app', [])
  .controller('AdamController', AdamController)
  .controller('AnujController', AnujController)
;

function AdamController($rootScope) {
  var vm = this;
  vm.prop = 'adam';
  
  vm.update = function() {
    $rootScope.$broadcast('propChange');
  };
}

function AnujController($scope) {
  var vm = this;
  vm.prop = '';

  $scope.$on('propChange', function(event) {
    event.currentScope.anuj.prop += 'x';
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app='app'>

  <head>
    <script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div ng-controller='AdamController as adam'>
      <input ng-model='adam.prop' ng-change='adam.update()'>
    </div>
    
    <div ng-controller='AnujController as anuj'>
      <p>{{ anuj.prop }}</p>
    </div>
  </body>

</html>

  1. Method on a Factory

angular
  .module('app', [])
  .factory('Factory', Factory)
  .controller('AdamController', AdamController)
  .controller('AnujController', AnujController)
;

function Factory() {
  return {
    anujProp: 'anuj',
    update: function() {
      this.anujProp += 'j';
    }
  };
}

function AdamController(Factory) {
  var vm = this;
  vm.factory = Factory;
}

function AnujController(Factory) {
  var vm = this;
  vm.factory = Factory;
}
<!DOCTYPE html>
<html ng-app='app'>

  <head>
    <script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div ng-controller='AdamController as adam'>
      <input ng-model='initial' ng-change='adam.factory.update()'>
    </div>
    
    <div ng-controller='AnujController as anuj'>
      <p>{{ anuj.factory.anujProp }}</p>
    </div>
  </body>

</html>

  1. Factory + $watch

angular
  .module('app', [])
  .factory('Factory', Factory)
  .controller('AdamController', AdamController)
  .controller('AnujController', AnujController)
;

function Factory() {
  return {
    shared: 'shared',
    related: 'related'
  };
}

function AdamController(Factory) {
  var vm = this;
  vm.factory = Factory;
}

function AnujController(Factory, $scope) {
  var vm = this;
  vm.factory = Factory;
  
  $scope.$watch('anuj.factory.related', function(newValue, oldValue, scope) {
    scope.anuj.factory.related = newValue.toUpperCase();
  });
}
<!DOCTYPE html>
<html ng-app='app'>

  <head>
    <script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div ng-controller='AdamController as adam'>
      <input ng-model='adam.factory.shared'>
      <input ng-model='adam.factory.related'>
    </div>
    
    <div ng-controller='AnujController as anuj'>
      <p>{{ anuj.factory.shared }}</p>
      <p>{{ anuj.factory.related }}</p>
    </div>
  </body>

</html>

  1. $scope inheritance

angular
  .module('app', [])
  .controller('AdamController', AdamController)
  .controller('AnujController', AnujController)
;

function AdamController($scope) {
  var vm = this;
  vm.adamProp = 'adam';
  vm.update = function() {
    var anuj = $scope.$parent.$$childTail.anuj;
    anuj.anujProp += 'j';
  };
}

function AnujController() {
  var vm = this;
  vm.anujProp = 'anuj';
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div ng-controller="AdamController as adam">
      <input ng-model="adam.adamProp" ng-change="adam.update()" />
    </div>
    <div ng-controller="AnujController as anuj">
      <p>{{ anuj.anujProp }}</p>
    </div>
  </body>

</html>
Adam Zerner
  • 17,797
  • 15
  • 90
  • 156
  • 1
    Although each of those may well be great solutions...this answer isn't a good answer since it isn't self contained. If you feel that this would benefit the community you really should include the code in the answer itself and explain why you ranked them the way you did...for example http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call or http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs – charlietfl Oct 02 '15 at 21:22
  • 1
    Thought this was a great answer. – inorganik Oct 02 '15 at 22:22