Angular ui-router在相同状态的子视图之间传递数据

时间:2022-02-04 10:31:03

How do I access other subviews in the same state. I am building a page with a toolbar on top and a sidebar and I want a button on the toolbar to open/close the sidebar and buttons in the sidebar to change the content. easy of it's all in the same controller but what I did is to use ui-router's subview feature like this:

如何访问处于相同状态的其他子视图。我正在构建一个顶部有一个工具栏和一个侧边栏的页面,我想要工具栏上的一个按钮来打开/关闭边栏中的侧边栏和按钮以更改内容。很简单它都在同一个控制器中,但我所做的是使用ui-router的子视图功能,如下所示:

.state('dash', {
    url: '/dash/:id',
    views: {
      nav: {
        controller: 'NavCtrl',
        controllerAs: 'ctrl',
        templateUrl: '/views/navbar.html'
      },
      sidebar: {
        controller: 'SidebarCtrl',
        controllerAs: 'ctrl',
        templateUrl: '/views/sidebar.html'
      },
      content: {
        controller: 'DashCtrl',
        controllerAs: 'ctrl',
        templateUrl: '/views/dash.html'
      }
    }
  })

UI looks like this:

UI看起来像这样:

Angular ui-router在相同状态的子视图之间传递数据

4 个解决方案

#1


11  

Define a resolve and use it as a place to store common data for the activated 'dash' state.

定义解析并将其用作存储激活的“破折号”状态的公共数据的位置。

app.config(function($stateProvider) {
  $stateProvider.state('dash', {
    url: '/',
    resolve: { 
      dashData: function() { 
        return { input: "default value" }; 
      } 
    },
    views: {
      nav: {
        controller: function() {

        },
        controllerAs: 'ctrl',
        template: '<h3>This is the Navbar</h3>'
      },
      sidebar: {  
        controller: function(dashData) { // Inject reference to resolve object
          this.dashData = dashData; 
        },
        controllerAs: 'ctrl',
        template: 'content data visible in ' + 
                     'the sidebar: <b>{{ ctrl.dashData.input }}<b>'
      },
      content: {
        controller: function(dashData) { // Inject reference to resolve object
          this.dashData = dashData;
        },
        controllerAs: 'ctrl',
        template: '<input type="text" ng-model="ctrl.dashData.input">' + 
                  'This is bound to dashData.input'
      }
    }
  })
});

Inject the shared object into each controller

将共享对象注入每个控制器

app.controller('DashCtrl', function(dashData, $scope) {
  $scope.dashData = dashData;
});
app.controller('... ....

I put this example in a plunker for you: http://plnkr.co/edit/8M1zXN0W5ybiB8KyxvqW?p=preview

我把这个例子放在了一个plunker中:http://plnkr.co/edit/8M1zXN0W5ybiB8KyxvqW?p = preview

#2


4  

This would be a good example of where an abstract parent state comes in handy:

这将是抽象父状态派上用场的一个很好的例子:

An abstract state can have child states but can not get activated itself. An 'abstract' state is simply a state that can't be transitioned to. It is activated implicitly when one of its descendants are activated.

抽象状态可以具有子状态但不能自行激活。 “抽象”状态只是一个无法转换的状态。当其中一个后代被激活时,它会被隐式激活。

https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states

https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states

And then especially this usecase:

然后特别是这个用例:

inherit $scope objects down to children

将$ scope对象继承到子级

Consider the following abstract parent state and it's child state:

考虑以下抽象父状态及其子状态:

$stateProvider.state('root', {
    abstract: true,
    url: '/dash',
    templateUrl: 'root.html',
    controller: 'rootController'
});

$stateProvider.state('dash', {
    parent: 'root',
    url: '/:id',
    views: {
        'navbar': {
            templateUrl: 'navbar.html',
            controller: 'navbarController'
        },
        'sidebar': {
            templateUrl: 'sidebar.html',
            controller: 'sidebarController'
        },
        'content': {
            templateUrl: 'content.html',
            controller: 'contentController'
        }
    }
});

Now you can store logic (and data) you need in your childstate in the controller of the abstract parent state:

现在,您可以在childstate中将所需的逻辑(和数据)存储在抽象父状态的控制器中:

angular.module('app').controller('rootController', [
             '$scope',
    function ($scope) {
        $scope.sidebar = {
            show: true
        };
        $scope.items = [{
            name: 'Alpha'
        }, {
            name: 'Bravo'
        },{
            name: 'Charlie'
        },{
            name: 'Delta'
        }];
        $scope.selected = $scope.items[0];
        $scope.select = function (item) {
            $scope.selected = item;
        }
    }
]);

Example of using this logic/data in a template of the child state, sidebar.html:

在子状态模板sidebar.html中使用此逻辑/数据的示例:

<ul class="nav nav-pills nav-stacked">
    <li ng-repeat="item in items" role="presentation">
        <a href="#" ng-click="select(item)">{{item.name}}</a>
    </li>
</ul>

Here's a complete example with your requirements, i could post all the code here but i think that would be a bit too much:

以下是您的要求的完整示例,我可以在这里发布所有代码,但我认为这有点太多了:

http://embed.plnkr.co/2jKJtFM0GWsylyLcAdne/

http://embed.plnkr.co/2jKJtFM0GWsylyLcAdne/

I'll gladly answer any question you may have, just holler. Good luck!

我很乐意回答你的任何问题,只是大喊大叫。祝你好运!

#3


1  

if you'd name your controllers differently with controller as, you could use the NavCtrl in the sidebarCtrl's template. Maybe use some boolean value that exists on the NavCtrl, that decides what to show in the sidebar? (from the comment)

如果您使用控制器命名控制器的方式不同,则可以使用sidebarCtrl模板中的NavCtrl。也许使用NavCtrl上存在的一些布尔值,它决定了侧边栏中显示的内容? (来自评论)

This should work, haven't tried it though.

这应该工作,但没有尝试过。

.state('dash', {
        url: '/dash/:id',
        views: {
          nav: {
            controller: 'NavCtrl',
            controllerAs: 'navCtrl',
            templateUrl: '/views/navbar.html'
          },
          sidebar: {
            controller: 'SidebarCtrl',
            controllerAs: 'sidebarCtrl',
            templateUrl: '/views/sidebar.html'
          },
          content: {
            controller: 'DashCtrl',
            controllerAs: 'dashCtrl',
            templateUrl: '/views/dash.html'
          }
        }
      })

sidebarService:

sidebarService:

angular.module('app').value('sidebarService', {show: true});

navCtrl something like this:

navCtrl是这样的:

function(sidebarService){
  var vm = this;
  vm.toggleSideBar = function(){sidebarService.show = !sidebarService.show;}//used in navbar.html
}

sidebarCtrl:

sidebarCtrl:

function(sidebarService){
  var vm = this;
  vm.showSideBar= sidebarService;
}

and then in sidebar.html you use the sidebar value service:

然后在sidebar.html中使用侧边栏值服务:

<div ng-if="sidebarCtrl.showSideBar.show">
<!--SideBar-->
</div

#4


1  

You can use events to communicate between controllers. Check the AngularJS documentation for $scope.$broadcast and `$scope.$on : https://docs.angularjs.org/api/ng/type/$rootScope.Scope

您可以使用事件在控制器之间进行通信。检查AngularJS文档中的$ scope。$ broadcast和`$ scope。$ on:https://docs.angularjs.org/api/ng/type/$rootScope.Scope

#1


11  

Define a resolve and use it as a place to store common data for the activated 'dash' state.

定义解析并将其用作存储激活的“破折号”状态的公共数据的位置。

app.config(function($stateProvider) {
  $stateProvider.state('dash', {
    url: '/',
    resolve: { 
      dashData: function() { 
        return { input: "default value" }; 
      } 
    },
    views: {
      nav: {
        controller: function() {

        },
        controllerAs: 'ctrl',
        template: '<h3>This is the Navbar</h3>'
      },
      sidebar: {  
        controller: function(dashData) { // Inject reference to resolve object
          this.dashData = dashData; 
        },
        controllerAs: 'ctrl',
        template: 'content data visible in ' + 
                     'the sidebar: <b>{{ ctrl.dashData.input }}<b>'
      },
      content: {
        controller: function(dashData) { // Inject reference to resolve object
          this.dashData = dashData;
        },
        controllerAs: 'ctrl',
        template: '<input type="text" ng-model="ctrl.dashData.input">' + 
                  'This is bound to dashData.input'
      }
    }
  })
});

Inject the shared object into each controller

将共享对象注入每个控制器

app.controller('DashCtrl', function(dashData, $scope) {
  $scope.dashData = dashData;
});
app.controller('... ....

I put this example in a plunker for you: http://plnkr.co/edit/8M1zXN0W5ybiB8KyxvqW?p=preview

我把这个例子放在了一个plunker中:http://plnkr.co/edit/8M1zXN0W5ybiB8KyxvqW?p = preview

#2


4  

This would be a good example of where an abstract parent state comes in handy:

这将是抽象父状态派上用场的一个很好的例子:

An abstract state can have child states but can not get activated itself. An 'abstract' state is simply a state that can't be transitioned to. It is activated implicitly when one of its descendants are activated.

抽象状态可以具有子状态但不能自行激活。 “抽象”状态只是一个无法转换的状态。当其中一个后代被激活时,它会被隐式激活。

https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states

https://github.com/angular-ui/ui-router/wiki/Nested-States-and-Nested-Views#abstract-states

And then especially this usecase:

然后特别是这个用例:

inherit $scope objects down to children

将$ scope对象继承到子级

Consider the following abstract parent state and it's child state:

考虑以下抽象父状态及其子状态:

$stateProvider.state('root', {
    abstract: true,
    url: '/dash',
    templateUrl: 'root.html',
    controller: 'rootController'
});

$stateProvider.state('dash', {
    parent: 'root',
    url: '/:id',
    views: {
        'navbar': {
            templateUrl: 'navbar.html',
            controller: 'navbarController'
        },
        'sidebar': {
            templateUrl: 'sidebar.html',
            controller: 'sidebarController'
        },
        'content': {
            templateUrl: 'content.html',
            controller: 'contentController'
        }
    }
});

Now you can store logic (and data) you need in your childstate in the controller of the abstract parent state:

现在,您可以在childstate中将所需的逻辑(和数据)存储在抽象父状态的控制器中:

angular.module('app').controller('rootController', [
             '$scope',
    function ($scope) {
        $scope.sidebar = {
            show: true
        };
        $scope.items = [{
            name: 'Alpha'
        }, {
            name: 'Bravo'
        },{
            name: 'Charlie'
        },{
            name: 'Delta'
        }];
        $scope.selected = $scope.items[0];
        $scope.select = function (item) {
            $scope.selected = item;
        }
    }
]);

Example of using this logic/data in a template of the child state, sidebar.html:

在子状态模板sidebar.html中使用此逻辑/数据的示例:

<ul class="nav nav-pills nav-stacked">
    <li ng-repeat="item in items" role="presentation">
        <a href="#" ng-click="select(item)">{{item.name}}</a>
    </li>
</ul>

Here's a complete example with your requirements, i could post all the code here but i think that would be a bit too much:

以下是您的要求的完整示例,我可以在这里发布所有代码,但我认为这有点太多了:

http://embed.plnkr.co/2jKJtFM0GWsylyLcAdne/

http://embed.plnkr.co/2jKJtFM0GWsylyLcAdne/

I'll gladly answer any question you may have, just holler. Good luck!

我很乐意回答你的任何问题,只是大喊大叫。祝你好运!

#3


1  

if you'd name your controllers differently with controller as, you could use the NavCtrl in the sidebarCtrl's template. Maybe use some boolean value that exists on the NavCtrl, that decides what to show in the sidebar? (from the comment)

如果您使用控制器命名控制器的方式不同,则可以使用sidebarCtrl模板中的NavCtrl。也许使用NavCtrl上存在的一些布尔值,它决定了侧边栏中显示的内容? (来自评论)

This should work, haven't tried it though.

这应该工作,但没有尝试过。

.state('dash', {
        url: '/dash/:id',
        views: {
          nav: {
            controller: 'NavCtrl',
            controllerAs: 'navCtrl',
            templateUrl: '/views/navbar.html'
          },
          sidebar: {
            controller: 'SidebarCtrl',
            controllerAs: 'sidebarCtrl',
            templateUrl: '/views/sidebar.html'
          },
          content: {
            controller: 'DashCtrl',
            controllerAs: 'dashCtrl',
            templateUrl: '/views/dash.html'
          }
        }
      })

sidebarService:

sidebarService:

angular.module('app').value('sidebarService', {show: true});

navCtrl something like this:

navCtrl是这样的:

function(sidebarService){
  var vm = this;
  vm.toggleSideBar = function(){sidebarService.show = !sidebarService.show;}//used in navbar.html
}

sidebarCtrl:

sidebarCtrl:

function(sidebarService){
  var vm = this;
  vm.showSideBar= sidebarService;
}

and then in sidebar.html you use the sidebar value service:

然后在sidebar.html中使用侧边栏值服务:

<div ng-if="sidebarCtrl.showSideBar.show">
<!--SideBar-->
</div

#4


1  

You can use events to communicate between controllers. Check the AngularJS documentation for $scope.$broadcast and `$scope.$on : https://docs.angularjs.org/api/ng/type/$rootScope.Scope

您可以使用事件在控制器之间进行通信。检查AngularJS文档中的$ scope。$ broadcast和`$ scope。$ on:https://docs.angularjs.org/api/ng/type/$rootScope.Scope