Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two views in one AngularUI Router state sharing scope

I am pretty new to the AngularUI Router and would like the use it for the following scenario:

The layout common to all pages includes a top navbar containing a menu with buttons on the right and a content section filling the space below. The page has several pages that I map to UI Router states (page1, page2, ...). Each page can have its own menu items and its own content. The menu needs to share the scope with the content since they interact (e.g. the save button submits the form in the content, it should only be enabled if the form is valid).

mockup

The HTML roughly looks like this:

<body>
    <nav class="...">
        <h1>my site</h1>
        <div>MENU SHOULD GO HERE</div>
    </nav>
    <div class="row">
        <div class="column ...">
            CONTENT SHOULD GO HERE
        </div>
    </div>        
</body>

Right now, I am using two parallel views and two controllers for each state. But this way, the two scopes/controllers cannot interact.

So how would you accomplish that?

like image 633
jack_kerouac Avatar asked Feb 20 '14 09:02

jack_kerouac


1 Answers

$scope is not the model, its a reference to a model, glue in between the data & the view. If $scopes in two, or more, controllers need to share one model/state/data use a singleton object instance by registering a angular service. That one service/factory can be injected into as many controllers as you like, and then everything can work off that one source of truth.

Heres a demo of 1 factory linking $scopes in navbar & body with ui-router http://plnkr.co/edit/P2UudS?p=preview (left tab only)

ui-router (viewC is navbar):

$stateProvider
.state('left', {
  url: "/",
  views: {
    "viewA": {
      controller: 'LeftTabACtrl',
      template: 'Left Tab, index.viewA <br>' +
                '<input type="checkbox" ng-model="selected2.data" />' +
                '<pre>selected2.data: {{selected2.data}}</pre>'
    },
    {...},
    "viewC": {
      controller: 'NavbarCtrl',
      template: '<span>Left Tab, index.viewC <div ui-view="viewC.list"></div>' +
                '<input type="checkbox" ng-model="selected.data" />' +
                '<pre>selected.data: {{selected.data}}</pre></span>'
    }
  }
})

Factory & Controllers:

app.factory('uiFieldState', function () {
    return {uiObject: {data: null}}
});

app.controller('NavbarCtrl', ['$scope', 'uiFieldState', '$stateParams', '$state',
    function($scope, uiFieldState, $stateParams, $state) {
        $scope.selected = uiFieldState.uiObject;
    }
]);

app.controller('LeftTabACtrl', ['$scope', 'uiFieldState', '$stateParams', '$state',
    function($scope, uiFieldState, $stateParams, $state) {
        $scope.selected2 = uiFieldState.uiObject;
    }
]);

As you can see, the factory object {uiObject: {data: null}} is injected into the controller with uiFieldState & then its simply $scope.selected = uiFieldState.uiObject; for connecting the factory to the scope ng-model="selected.data" .`

like image 120
cheekybastard Avatar answered Sep 27 '22 22:09

cheekybastard