Separate controller per tab in angular-material w/ ui-router Separate controller per tab in angular-material w/ ui-router javascript javascript

Separate controller per tab in angular-material w/ ui-router


If you name your ui-view elements (e.g. <div ui-view="player"></div>) then you can target them in your $stateProvider config.

So, given the following markup in template.html:

<md-tabs md-selected="currentTab">    <md-tab label="Player" ui-sref="tabs.player">        <div ui-view="player"></div>    </md-tab>    <md-tab label="Map" ui-sref="tabs.map">        <div ui-view="map"></div>    </md-tab></md-tabs>

You could target each ui-view element (and update the currentTab index) with the following $stateProvider config:

.state('tabs', {    abstract: true,    url: '/tabs',    templateUrl: 'template.html',    controller: function($scope) {      $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {        $scope.currentTab = toState.data.selectedTab;      });    }  }).state('tabs.player', {    url: '/player',    data: {      'selectedTab': 0    },    views: {      'player': {        controller: playerController      }    }  }).state('tabs.map', {    url: '/map',    data: {      'selectedTab': 1    },    views: {      'map': {        controller: mapController      }    }  })

All you need to do now is define playerController and mapController. You can still load partial templates etc. into the ui-view, see the section on Multiple Named Views.


I was able to get this going by just doing

index.html

<md-toolbar ng-controller="NavigationController as vm"            ng-include="'app/components/navbar/navbar.html'"            class="md-default-theme" ></md-toolbar><md-content ui-view            md-scroll-y            class="md-default-theme"            role="main"            flex></md-content>

navbar.html

<md-tabs md-selected="vm.currentTab" md-stretch-tabs="always" class="main-toolbar">    <md-tab label="Home" ui-sref="home"></md-tab>    <md-tab label="Portfolio" ui-sref="portfolio"></md-tab>    <md-tab label="Contact" ui-sref="contact"></md-tab></md-tabs>

app.js

$stateProvider    .state('home', {        url: '/',        data: {            'selectedTab' : 0        },        templateUrl: 'app/components/main/main.html',        controller: 'MainController as vm'    })    .state('portfolio', {        url: '/portfolio',        data: {            'selectedTab' : 1        },        templateUrl: 'app/components/portfolio/portfolio.html',        controller: 'PortfolioController as vm'    })    .state('contact', {        url: '/contact',        data: {            'selectedTab' : 2        },        templateUrl: 'app/components/contact/contact.html',        controller: 'ContactController as vm'    });

navigation.controller.js

function NavigationController($scope) {    var vm = this;    $scope.$on('$stateChangeSuccess', function(event, toState) {        vm.currentTab = toState.data.selectedTab;    });}


For anyone coming from google and not using ui-router, you can do the same thing with the default ng-router:In your index file place the tabs code:

<md-tabs md-selected="0" ng-controller="TabCtrl">    <md-tab ng-repeat="tab in tabs" md-on-select="switchTab($index)" label="{{tab}}">        <div ng-view></div>     </md-tab></md-tabs>

Then create TabCtrl:

// Define the titles of your tabs$scope.tabs = ["Player", "Map"];// Change the tab$scope.switchTab = function(index) {    switch(index) {        case 0: $location.path('/player');break;        case 1: $location.path('/map');break;    }}

Finally define your routes in your config:

.when( '/player', {    templateUrl: 'partials/player.html',    controller: 'PlayerCtrl'}).when( '/map', {    templateUrl: 'partials/map.html',    controller: 'MapCtrl'});