Javascript 带有 ui-router 的角度材料中的每个选项卡单独的控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27221222/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:53:11  来源:igfitidea点击:

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

javascriptangularjsangular-ui-routermaterial-designangular-material

提问by Seiyria

I'm trying to implement my md-tabsso each md-tabis a separate state using angular-material. My current markup looks like this:

我正在尝试实现我的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)

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?

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

回答by James Spencer

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

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

So, given the following markup in template.html:

因此,鉴于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-viewelement (and update the currentTab index) with the following $stateProvider config:

您可以ui-view使用以下 $stateProvider 配置来定位每个元素(并更新 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
      }
    }
  })

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

您现在需要做的就是定义playerControllermapController。您仍然可以将部分模板等加载到 中ui-view,请参阅多命名视图部分

回答by JimmyBob

I was able to get this going by just doing

我能够做到这一点

index.html

索引.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

导航栏.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

应用程序.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

导航控制器.js

function NavigationController($scope) {

    var vm = this;

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

}

回答by soote

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:

对于来自 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>

Then create TabCtrl:

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

回答by alox wagnor

Here, a bit changed with the original docu(https://material.angularjs.org/#/demo/material.components.tabs):

在这里,与原始文档(https://material.angularjs.org/#/demo/material.components.tabs)略有不同:

I added some comments. If somebody leave or refresh your page, hes going enter the same tab...

我添加了一些评论。如果有人离开或刷新您的页面,他将进入相同的选项卡...

HTML:

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>

Controller:

控制器:

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

factroy:

工厂:

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

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

回答by Will

An alternative that allows linking directly to the tab, and preserves forward and back behavior is to use the HTML structure from this answer, then inject $transitionsto use the onSuccesslistener:

允许直接链接到选项卡并保留向前和向后行为的替代方法是使用此答案中的 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
    }
  )
})

A working example is at: https://dysbulic.github.io/angular-tabs/

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