Complete Solution for Data Passing Between Controllers in AngularJS: Service Pattern and Event Broadcasting

Nov 21, 2025 · Programming · 12 views · 7.8

Keywords: AngularJS | Data_Passing | Service_Factory | Controller_Communication | Shopping_Cart_Implementation

Abstract: This article provides an in-depth exploration of data communication mechanisms between controllers in AngularJS, focusing on the service factory pattern for data sharing. Through a reconstructed product list and shopping cart scenario, it demonstrates how to achieve cross-controller data synchronization using factory services, while comparing the applicable scenarios of event broadcasting. The article includes complete code implementations, architectural design principles, and best practice guidelines, offering reliable data communication solutions for AngularJS developers.

Overview of Data Communication Between AngularJS Controllers

In AngularJS single-page application development, data passing between controllers is a common requirement. When applications contain multiple independent functional modules, how to efficiently and reliably share data between different controllers becomes a key consideration in architectural design. This article systematically analyzes various data communication mechanisms provided by AngularJS based on practical product management scenarios.

Core Implementation of Service Factory Pattern

Service factories are the preferred solution for implementing data sharing in AngularJS. By creating injectable singleton services, we can maintain unified data states across multiple controllers.

angular.module('shoppingApp').factory('productService', function() {
  var productList = [];
  
  var addProduct = function(product) {
    if (product && !productList.some(function(p) { return p.id === product.id; })) {
      productList.push(product);
    }
  };
  
  var getProducts = function() {
    return angular.copy(productList);
  };
  
  var clearProducts = function() {
    productList.length = 0;
  };
  
  return {
    addProduct: addProduct,
    getProducts: getProducts,
    clearProducts: clearProducts
  };
});

Implementation Details of Product Controller

The product controller is responsible for displaying product lists and handling user selection operations. By injecting the product service through dependency injection, the controller can add user-selected products to shared data.

angular.module('shoppingApp').controller('ProductController', 
['$scope', 'productService', 'productFactory', 
function($scope, productService, productFactory) {
  
  $scope.products = [];
  
  productFactory.getProducts().then(function(response) {
    $scope.products = response.data;
  }, function(error) {
    console.error('Failed to load products:', error);
  });
  
  $scope.selectProduct = function(product) {
    productService.addProduct(product);
    console.log('Product added to cart:', product.name);
  };
}]);

View Layer Interaction Implementation

In HTML templates, we use the ng-repeat directive to render product lists and bind selection events through ng-click.

<div ng-controller="ProductController">
  <h3>Product List</h3>
  <ul class="product-list">
    <li ng-repeat="product in products" 
        ng-click="selectProduct(product)"
        class="product-item">
      {{product.name}} - {{product.price | currency}}
    </li>
  </ul>
</div>

Shopping Cart Controller Implementation

The shopping cart controller obtains the list of user-selected products in real-time by injecting the same product service and supports dynamic view updates.

angular.module('shoppingApp').controller('CartController', 
['$scope', 'productService', 
function($scope, productService) {
  
  $scope.cartItems = [];
  
  var updateCart = function() {
    $scope.cartItems = productService.getProducts();
    $scope.totalPrice = $scope.cartItems.reduce(function(sum, item) {
      return sum + (item.price || 0);
    }, 0);
  };
  
  $scope.$watch(function() {
    return productService.getProducts().length;
  }, function(newLength, oldLength) {
    if (newLength !== oldLength) {
      updateCart();
    }
  });
  
  $scope.removeFromCart = function(index) {
    var items = productService.getProducts();
    items.splice(index, 1);
    updateCart();
  };
  
  updateCart();
}]);

Shopping Cart View Template

The shopping cart view dynamically displays user-selected products and provides removal functionality.

<div ng-controller="CartController">
  <h3>Shopping Cart</h3>
  <div class="cart-container" ng-if="cartItems.length > 0">
    <ul class="cart-items">
      <li ng-repeat="item in cartItems track by $index" 
          class="cart-item">
        <span class="item-name">{{item.name}}</span>
        <span class="item-price">{{item.price | currency}}</span>
        <button ng-click="removeFromCart($index)" 
                class="remove-btn">
          Remove
        </button>
      </li>
    </ul>
    <div class="cart-total">
      Total: {{totalPrice | currency}}
    </div>
  </div>
  <div class="empty-cart" ng-if="cartItems.length === 0">
    Cart is empty
  </div>
</div>

Supplementary Analysis of Event Broadcasting Solution

Although service factories are the primary recommended solution, event broadcasting still has its value in specific scenarios. Cross-level event communication can be achieved through $rootScope.$broadcast.

// Add event broadcasting functionality to product service
angular.module('shoppingApp').factory('productService', 
['$rootScope', function($rootScope) {
  var productList = [];
  
  var addProduct = function(product) {
    productList.push(product);
    $rootScope.$broadcast('productAdded', product);
  };
  
  return {
    addProduct: addProduct,
    getProducts: function() { return productList; }
  };
}]);

// Listen to events in shopping cart controller
$scope.$on('productAdded', function(event, product) {
  console.log('Product added via event:', product.name);
  $scope.cartItems = productService.getProducts();
});

Architectural Design Best Practices

When designing controller communication in AngularJS applications, the following principles should be followed: prioritize service factories for data sharing, consider event broadcasting only when loose coupling is needed; maintain single responsibility of services, avoid handling view logic in services; use data monitoring mechanisms to ensure real-time view updates; properly handle errors and edge cases to enhance application stability.

Performance Optimization Recommendations

For large-scale applications, it's recommended to optimize data operations in services: use track by to improve ng-repeat performance; avoid complex computations in $watch; consider using debounce for frequent data updates; use one-way data flow patterns in appropriate scenarios to reduce unnecessary view updates.

Conclusion

AngularJS provides flexible and diverse mechanisms for data passing between controllers. The service factory pattern, with its simplicity, maintainability, and performance advantages, becomes the preferred solution for most scenarios. Through the complete implementation and in-depth analysis in this article, developers can choose appropriate data communication strategies based on specific requirements to build efficient and reliable AngularJS applications.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.