带有 ui-router 的 angular-material 中每个选项卡的单独控制器

Posted

技术标签:

【中文标题】带有 ui-router 的 angular-material 中每个选项卡的单独控制器【英文标题】:Separate controller per tab in angular-material w/ ui-router 【发布时间】:2015-01-29 00:50:40 【问题描述】:

我正在尝试实现我的md-tabs,因此每个md-tab 都是使用角度材料的单独状态。我当前的标记如下所示:

  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)

不过,我认为这不是 ui-router 的有效标记。是否可以使用当前版本的 angular-material 和 ui-router 做到这一点?

【问题讨论】:

【参考方案1】:

如果您命名您的 ui-view 元素(例如 <div ui-view="player"></div>),那么您可以在 $stateProvider 配置中定位它们。

因此,鉴于 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>

您可以使用以下 $stateProvider 配置定位每个 ui-view 元素(并更新 currentTab 索引):

.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
      
    
  )

您现在需要做的就是定义 playerControllerma​​pController。您仍然可以将部分模板等加载到ui-view,请参阅Multiple Named Views 部分。

【讨论】:

有趣。这似乎是一种浪费和笨拙的方法(不是你可以控制它),但它似乎也是唯一的方法。我会试试看。非常感谢! 不用担心,只是遇到了同样的问题,并且命名视图是我能解决的唯一方法。如果它对您有用,如果您能接受答案,那就太好了。谢谢! 我成功地实现了这一点。非常好的答案,感谢有关设置 selectedTab 的一些信息 - 起初我很困惑,但后来我刷新了页面,它击中了我。 我想,我实现了这个,但我的模板没有显示。我这样使用它:views: 'invitations': template: '

My Contacts

' --- 但是 div 是空的: --- 任何想法或一个可行的解决方案?
谢谢.. 但它仍然没有按预期工作。尝试将模板添加到播放器/地图视图。单击选项卡时会更新,但导航时会更新失败...【参考方案2】:

对于来自 google 且不使用 ui-router 的任何人,您可以使用默认的 ng-router 执行相同的操作: 在您的索引文件中放置标签代码:

<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>

然后创建 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;
    

最后在你的配置中定义你的路线:

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

【讨论】:

md-selected 需要根据哪个选项卡处于活动状态进行更改,否则您会遇到奇怪的重定向问题。【参考方案3】:

这里,与原来的docu(https://material.angularjs.org/#/demo/material.components.tabs)有点不同:

我添加了一些 cmets。如果有人离开或刷新你的页面,他会进入同一个标签...

HTML:

  <md-tabs md-selected="selectedIndex">

<md-tab ng-repeat="tab in tabs" md-on-select="announceSelected(tab, $index)" md-on-deselect="announceDeselected(tab)" ng-disabled="tab.disabled" label="tab.title">

   </md-tab>
 </md-tabs>

控制器:

var tabs = [
              title: 'welcome',
              title: 'profile',
            ];



     $scope.selectedIndex = 0;
    // $scope.selectedIndex = parseInt($cookies.selectedIndex);
     $scope.tabs = tabs;



$scope.announceSelected = function(tab, index) 

 //$cookies["selectedIndex"] = index;
       RedirectService.To(tab.title);

工厂:

app.factory('RedirectService', function ($location)
        return
                    To : function(key)

                        return $location.path(key)
                    ,
            ;
);

【讨论】:

【参考方案4】:

我可以通过这样做来实现这一点

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;
    );


【讨论】:

不需要绑定额外的属性。使用 唯一的区别是接受的答案使用标签正文和“滑动”进出。 +1 这对我不起作用,出现角度表达式错误。任何人都会有帮助... 它不会在标签更改时保持动画【参考方案5】:

允许直接链接到选项卡并保留前进和后退行为的替代方法是使用来自 this answer 的 HTML 结构,然后注入 $transitions 以使用 onSuccess 侦听器:

angular.module('tabs', ['ngMaterial', 'ui.router'])
.config(['$stateProvider', '$urlRouterProvider',
  ($stateProvider, $urlRouterProvider) => 
    $stateProvider
    .state('home', 
      url: '/',
      data:  selectedTab: 0 ,
      template: '<p>HOME</p>',
    )
    .state('portfolio', 
      url: '/portfolio',
      data:  selectedTab: 1 ,
      template: "<p>'FOLIO</p>",
    )
    .state('contact', 
      url: '/contact',
      data:  selectedTab: 2 ,
      template: "<p>'TACT</p>",
    )
  
  ])
.controller('NavigationController', function($scope, $transitions) 
  $transitions.onSuccess(,
    function(transition) 
      var $state = transition.router.stateService
      var currentTab = $state.$current.data.selectedTab
      $scope.selectedTab = currentTab
    
  )
)

一个工作示例位于:https://dysbulic.github.io/angular-tabs/

【讨论】:

以上是关于带有 ui-router 的 angular-material 中每个选项卡的单独控制器的主要内容,如果未能解决你的问题,请参考以下文章

不能使用带有 ui-router AngularJS 的视图使用不同的控制器

带有angular1.5组件meteor和ui-router的动态标题

带有 ui-router 的 angular-material 中每个选项卡的单独控制器

使用干净的字符串 url,而不是使用带有 ui-router 的 mongo 对象 id 的 url

Angular UI-Router,父 ui-view 渲染,但带有模板的子视图不渲染

ui-router:中间模板