Search code examples
angularjsangularjs-service

How angular service changes can be handled in somewhere else?


It is a common practice in AngularJS to make and use custom services for DOM manipulation and share the same functionality across different parts of the UI my question is also related to this case and is as follow:

There is a sidebar component in my application and a button for minimizing the sidebar on click but the problem is that their controllers are different so I have created a service in the same module named sidebarService and injected this service into both controllers but while the data changes in the service through an event by a controller I can't handle it in another controller so how to do this:

app-module.js

(function() {
  'use strict';

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

});

sidebar-service.js

(function() {
  'use strict';

  angular.module('app')
    .factory('sidebarService', function() {

    var showClass = false;

    return {

      toggle: function() {
        showClass = !showClass;
      },

      isClassShown: function() {
        return showClass;
      }

    };
  });

});

app-controller.js

(function() {
  'use strict';

  angular.module('app')
    .controller('App', ['sidebarService', function(sidebarService) {

    var appVm = this;

    appVm.isClassShown = function() {

      return sidebarService.isClassShown();

    };

  }]);

});

navbar-controller.js

(function() {
  'use strict';

  angular.module('app')
    .controller('Navbar', ['sidebarService', function(sidebarService) {

    var navbarVm = this;

    navbarVm.toggleSidebar = function() {

      sidebarService.toggle();

    };
  }]);

})();

index.html

<!DOCTYPE html>
<html ng-app="app">
<head>
  <title>My App</title>
  <!-- ... -->
</head>
<body ng-controller="App as app">
  <ul ng-controller="Navbar as navbar">
    <li>
      <a href="#" ng-click="navbar.toggleSidebar()">Toggle Sidebar</a>
    </li>
    <!-- ... -->
  </ul>
  <div class="sidebar" ng-class="{mini:app.isClassShown()}">
    <!-- ... -->
  </div>
</body>
</html>

Solution

  • It is also possible and is a little solution for the issue you faced with to use a property of your parent scope while AngularJS scopes are using the prototypical inheritance concept then your parent scope property will be available in child scopes but to be sure to make changes from child scope and also change in parent scope use JavaScript objects based scope properties.

    For more on this topic you can read here.

    So according to my explanation and recommendation do as follow:

    app-controller.js

    (function() {
      'use strict';
    
      angular.module('app')
        .controller('App', ['$scope', function($scope) {
    
        $scope.someObj = {
    
          sidebarClass: false
    
        };
    
      }]);
    
    });
    

    index.html

    <!DOCTYPE html>
    <html ng-app="app">
    <head>
      <title>My App</title>
      <!-- ... -->
    </head>
    <body ng-controller="App as app">
      <ul ng-controller="Navbar as navbar">
        <li>
          <a href="#" ng-click="someObj.sidebarClass = !someObj.sidebarClass">Toggle Sidebar</a>
        </li>
        <!-- ... -->
      </ul>
      <div class="sidebar" ng-class="{mini:someObj.sidebarClass}">
        <!-- ... -->
      </div>
    </body>
    </html>