如何在angularjs ui路由器的状态之间共享$ scope数据?


71

在不使用服务或在父控制器中构造观察程序的情况下,如何使子状态访问主控制器的$scope

  .state("main", {
      controller:'mainController',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

我无法在子状态下访问mainController范围-或者我正在获取该范围的另一个实例-不是我想要的。我觉得我缺少一些简单的东西。在状态对象中有一个共享的数据配置选项,但是我不确定是否应该将其用于这样的事情。


子级可以访问父级。您可以用plunker复制您的问题吗?
tymeJV 2014年

1
那是一个很好的例子,但是我将如何使用控制器作为语法而不是$ scope?
Paul Erdos 2015年

我想知道; 我正在尝试做同样的事情,但是担心$scope即使我使用controller as语法(并且不在$scope控制器的代码中使用-只需将其提供给ui-router),也可能需要注入控制器。
Mawg说恢复Monica

Answers:


108

创建了工作的插件,展示了如何使用$scope和UI-Router。

状态定义未更改:

$stateProvider
    // States
 .state("main", {
      controller:'mainController',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

但是每个状态可以有不同的控制器。为什么?因为每个view每个获得new 实例的定义controller。因此,尽管我们mainController喜欢下面的代码,但可以肯定的是,如果导航到状态'main.2',它将被实例化两次。

controller('mainController', function ($scope) {
  $scope.Model = $scope.Model || {Name : "xxx"};
})

但是我们在这里可以看到的是,我们检查是否$scope.Model已经存在...,如果没有(父状态),则使用新实例实例 化它{Name : "xxx"}

好吧,我要说的是:只有父国家才能初始化$scope.Model。所有其他人都将得到满足。怎么样?好吧,这就是答案:

仅按视图层次结构的作用域继承

请记住,如果状态的视图是嵌套的,则作用域属性仅沿状态链继承。范围属性的继承与状态的嵌套无关,而与视图(模板)的嵌套无关。

完全有可能存在嵌套状态,这些状态的模板会在站点内各个非嵌套位置填充ui视图。在这种情况下,您不能期望在子状态的视图中访问父状态视图的范围变量。

因此,如文档中所述。由于我们的子视图嵌套在父视图中,因此将继承作用域。

了解范围

在AngularJS中,子作用域通常在原型上从其父作用域继承。
...

有一个 '。' 在您的模型中,将确保原型继承在起作用。

// So, use
<input type="text" ng-model="someObj.prop1"> 
// rather than
<input type="text" ng-model="prop1">.

就是这样。我们从UI-Router视图和角度范围获得继承,并且因为我们巧妙地使用了引用类型(Model),即定义中确实包含'.'ng-model-我们现在可以共享数据

注意:点号为“。” 在ng-model="Model.PropertyName简单的手段,是有reference对象Model {}的一些属性:PropertyName

这里检查工作示例


9
这是非常有用的。感谢您抽出宝贵的时间有条理地解释这一点-蒸馏的水平并没有被忽视。我根据您的建议重新构造了stateProvider.state对象和我的模板,一切都按照我希望的方式工作:scope沿链向下继承-我在构建视图时不考虑这个基本原理而感到很傻-再次感谢您我希望所有关于SO的答案都经过深思熟虑。
sjt003 2014年

Radim,非常感谢您在SO方面的帮助!
James Drinkard

@Radim Kohler我的登录状态有问题。您能帮我解决我的问题

谁知道,因为我删除了“ || {};” 在mainController里面不起作用?
西尔维奥·特罗亚

@Radim科勒有什么办法可以帮我这个 stackoverflow.com/questions/58126482/...
小号德拉

15

您可以通过$ rootScope获得整个范围。如果只需要一部分示波器,则ui-router具有自定义数据功能。

这是一个多步骤表格。我需要路由包含有关流程中步骤的信息。

首先,我有一些使用UI-router的路由:

  // Sign UP routes
  .state('sign-up', {
    abstract: true,
    url: '/sign-up',
    controller: 'SignupController',
    templateUrl: 'sign-up/index.html',
  })
  .state('sign-up.start', {
    url: '-start',
    templateUrl: 'sign-up/sign-up.start.html',
    data: { step: 0, title: 'Welcome to Mars!', },
  })
  .state('sign-up.expertise', {
    url: '-expertise',
    templateUrl: 'sign-up/sign-up.expertise.html',
    data: { step: 1, title: 'Your Expertise'},
  })

注意:

  • data每条路线中的元素。
  • abstract州有SignupController。这是此多步骤表单的唯一控制器。该abstract不是必需的,但是是有道理的,这个用例。

SignupController.js

angular.module('app').controller('SignupController', function($scope, $state) {
  $scope.state = $state;
});

在这里,我们得到ui-router$state并放在上面$scope

这是主要模板'sign-up / index.html',

<h2>{{state.current.data.title}}</h2>

<div>This is a multi-step-progress control {{state.current.data.step}}</div>

<form id="signUpForm" name="signUpForm" novalidate>
  <div ui-view></div>
</form>

子模板可以是他们喜欢的任何模板。


1
这节省了我一些时间。感谢分享
塔尔哈·马苏德

2
而且,如果您想简化视图模板中的$ state,则可以这样操作:$scope.state = $state.current.data;在视图中:{{state.title}}
Paula Fleck

9

这个想法是在父级->子级继承中使用作用域:

 .state("main", {
      controller:'mainController',
      abstract: true,
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController1',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController2',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

比用法简单,您有3个控制器,一个是共享的(mainController),每个视图都有它自己的。


2
然后使用以下命令在子控制器中访问父级的$ scope:$ scope。$ parent
samneric

我得到的范围甚至都没有提到“抽象:真实”,所以如果我不提及它有什么弊端
sandeep_kosta

8

如果您使用嵌套视图,则不要编写任何其他Controller。这样,他们将共享相同的控制器数据。

.state("main", {
            url: "/main",
            templateUrl: "templates/Ders",
            controller: "DersController as DersC"
       }).state("main.child1", {
            url: "/child1",
            templateUrl: "templates/Ders/child1"
       }).state("main.child2", {
            url: "/child2",
            templateUrl: "templates/Ders/child2"
        })

3
如果我要分别为child1和child2使用child1Controller和child2Controller怎么办?
约翰·

1

将共享变量分组为可以在每个控制器中访问的服务的最简单解决方案不是最简单的解决方案吗?...


1
这是一个简单的解决方案,但不会令人惊奇,例如(1)视图如何访问父控制器(干净地使用controller as)和(2)require如果控制器可以有依赖的控制器实例,如何将父控制器注入指令(干净地使用)。注入他们吗?
兰登2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.