Seiyria Seiyria - 4 months ago 218
Javascript Question

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

I'm trying to implement my

md-tabs
so each
md-tab
is a separate state using angular-material. My current markup looks like this:

md-tabs.is-flex.auto-flex(selected="selectedIndex",layout="vertical")
md-tab(on-select="selectTab(0)",label="Player",ui-sref="state1")
div.tab(ui-view)

md-tab(on-select="selectTab(1)",label="Map",ui-sref="state2")
div.tab(ui-view)


I don't think this is valid markup for ui-router, though. Is it possible to do this with the current version of angular-material and ui-router?

Answer

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.