1

I'm trying to implement a site with two main content 'panes' (imagine two columns each half the width of the page). The panes should be able to change independent of each other and have their own controllers and be able to pass data between each other (so the user can navigate through a bunch of pages on the left pane while the right pane stays the same without reloading and vice versa, and a change in the left pane can update data showing up in the right pane).

I've looked through a bunch of examples/tutorials on UI Router but can't seem to find a good example of how to implement what I'm trying to do. All of them seem to show either just examples for single nested views (so a single view within a larger view) or show multiple views but not how to change the views independent of each other.

I'd like to do this with a single <div ui-view></div> in the index.html file (as opposed to multiple ui-views) so that I can have everything happening within the single parent ui-view and not in the index.html file.

Right now I have something like the following js file:

config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise('/home');
      $stateProvider
      .state('home', {
            url: '/home',
            views: {
                '': { templateUrl: 'views/home.html' },
                'left@home': { 
                  templateUrl: 'views/charting/chartHome.html',
                },
                'right@home': { 
                    templateUrl: 'views/view1.html',
                    controller: 'View1Ctrl'
                }
            }

        });
    }]);

and the following HTML for home.html:

<div>
    <h1>This is home</h1>
</div>
<div ui-view='left'>
</div>
<div ui-view='right'>
</div>

Can anyone help with this? Or is this the wrong way to be thinking about the site? If so what should I be doing?

Thanks!

1 Answer 1

1

This is pretty complicated to solve with ui-router.

I've created this fiddle to give ui-router nested states a try. It works but it is gettting ugly quickly.

It works like this: home.main.left route changes only the left view and uses the right view from home.main. It would be better to have both view states independent from each other but I'm not sure how to do that with ui-router.

I think it would be better to use ui-router to do the navigation of the left part and use a custom directive for the right part (or the other way round). To communicate to the directive you can use $emit/$broadcast.

Changing the route of the left part is also possible from the directive with links ui-sref or with $state.go(...) method.

Please have a look at the demo below or in this jsfiddle.

angular.module('demoApp', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise('/home');
      $stateProvider
      .state('home', {
          templateUrl: 'views/home.html',
          abstract: true
      })
      .state('home.main', {
            url: '/home',
            templateUrl: 'views/charting/chartHome.html',
          	controller: 'LeftCtrl'
        })
      .state('home.left', {
            template: 'home.left <a href="#" ui-sref="home.left1">left1 change</a><br/>{{hello}}',
          controller: 'LeftCtrl'
          
        })
      .state('home.left1', {
            template: 'home.left1 <a href="#" ui-sref="home.left2">left2 change</a>'
        })
      .state('home.left2', {
            template: 'home.left2 <a href="#" ng-click="triggerDirective()">change directive</a>',
          controller: function($scope) {
          	$scope.triggerDirective = function() {
            	console.log('do directive action');
                $scope.$emit('rightContent:changeMsg', 'new content');
                // emit to rootscope because rightcontent is not a child of leftcontent
            };
          }
        })
      
      
    }])
.directive('rightContent', function() {
	return {
    	restrict: 'EA',
        template: 'Some static content or other stuff from directive. <strong>{{message}}</strong>',
        controller: function($scope, $rootScope) {
            $scope.message = 'hello from directive.';
        	$rootScope.$on('rightContent:changeMsg', function(evt, message) {
                console.log(message);
            	$scope.message = message;
            });
        }
    }
})
.controller('LeftCtrl', function($scope){
    
    $scope.hello = 'hello from left';
})
.controller('appController', function($scope) {
});
.left {
    float: left;
    width: 50%;
    height: 200px;
    background: lightgreen;
}


.right {
    float: right;
    width: 50%;
    height: 200px;
    background: lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>

<div ng-app="demoApp" ng-controller="appController">
    <script type="text/ng-template" id="views/home.html">
        <div>
            <h1>This is home</h1>
        </div>
        <div class="wrapper">
            <div ui-view="" class="left">
            </div>
            <div class="right">
                <right-content></right-content>
            </div>
            <a href="#" ui-sref="home.main">home</a>
        </div>
    </script>
    <script type="text/ng-template" id="views/charting/chartHome.html">
        left {{hello}}
        <a href="#" ui-sref="home.left">left change</a>
    </script>
    <script type="text/ng-template" id="views/view1.html">
        right {{hello}}
    </script>
    
    <div ui-view=""></div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the feedback, AWolf! Do you know if there's any good way to do it entirely with UI router instead of custom directives? I tried using the first method you gave a fiddle for, but it seems you can't really change states freely within pre-defining everything which as you say gets ugly quickly. If not, do you know any good more in-depth examples of the directive method you suggested that you think would be good to follow? Both right and left "panes" would be relatively complex in my potential site so I want to make sure I can make it very flexible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.