Search code examples
angularjsangular-ui-routermultiple-views

AngularJS Multiple views with shared logic design pattern


I'm using ui-router and my layout is divided into 2 ui-views, side-bar and main content

the side-bar offers options that changes the main content model (altering values, setting filters) and that's a problem because as far as I understand they can never share same controller (instance)

at this point there are two solutions I'm considering, 1. Working with one view moving the sidebar into the main view that way they will reside within a single controller instance, It's a bit ugly but still a solution 2. communicate between controllers with a messaging, invoking whatever needed in that disconnected matter

I don't like neither of those solutions, I'll be happy to get your design proposals

current routing def example (mind that same layout is common for my application and in used repeatedly:

$stateProvider.state('home', {
                url: "/home",
                views: {
                    main: {               
                        templateUrl:"homeTemplate.html",
                        controller: "HomeController"
                    },
                    sidebar: {templateUrl: "homeSidebarTemplate.html"}
                }
            })

Solution

  • Take a look at angular services

    You can use them for these purposes. A service is a singleton in which you can share data between any module. Put your data into the service and use it as a model in your main view and side bar.

    For example:

    angular.module('myApp.someNamespace', [])
      .factory('someService', function () {
    
      var service = {};
      service.myList = {1,2,3};
      service.myMenu = {'apples', 'oranges', 'pears'}
    
      service.addToList = function(number) {
       service.myList.push(number);
      }
      return service;
    });
    

    inject this service into your controller and sidebar directive:

    angular.module('myApp.myControllers', [])
        .controller('myCtrl', function ($scope, someService) {
    
        $scope.model = someService;
    });
    

    In your view bind to your service variables/methods:

    <div ng-repeat="number in model.myList">
       <input type="number" ng-model="number"/>
    </div>
    <input type="number" ng-model="newNumber"/>
    <button ng-click="model.addToList(newNumber)">Add</button>
    

    Another advantage of using this pattern is that your views will stay where you were when navigating back and forth (more stateful), because it gets the data from your singleton service. Also you'd only need to get the data from your api once (until you refresh your browser ofcourse).