AngularJS,路由之间传递范围


87

我遇到的情况是表单跨越了几页(可能并不理想,但这就是事实)。我想为整个表单提供一个范围,以便您随身携带,以便用户在步骤之间来回移动时,很容易记住状态。

所以我需要用非常伪的代码来做:

  1. $scope.val = <Some dynamic data>
  2. 单击一个链接,然后将其路由到新模板(可能使用同一控制器)。
  3. $scope.val 值应仍与上一页相同。

是否以某种方式持久保存示波器的数据是解决此问题的正确方法,还是还有其他方法?您是否甚至可以创建一个在路由之间具有持久作用域的控制器,当然除了将其保存在数据库中。


就像ganaraj一样:在这里您可以找到一个非常不错的博客条目,其中包含有关如何让不同的控制器进行通信的截屏视频。还有一些有用的jsfiddles可以玩。我希望它能帮助到onehungrymind.com/angularjs-communication-between-controllers
F Lekschas

Answers:


138

您需要使用服务,因为服务将在您的应用程序的整个生命周期中持续存在。

假设您要保存与用户有关的数据

这是您定义服务的方式:

app.factory("user",function(){
        return {};
});

在第一个控制器中:

app.controller( "RegistrationPage1Controller",function($scope,user){
    $scope.user = user;
    // and then set values on the object
    $scope.user.firstname = "John";
    $scope.user.secondname = "Smith";
});

app.controller( "RegistrationSecondPageController",function($scope,user){
        $scope.user = user;
        // and then set values on the object
        $scope.user.address = "1, Mars";

    });

6
啊!我之前曾尝试过,但由于两个路由都使用了相同的控制器,因此无法正常工作,因此在每个新路由中,默认值都会覆盖我在上一页中输入的值。使用两个控制器或没有默认值,这种情况不再发生。谢谢!
Erik Honn

1
Value Recipe docs.angularjs.org/guide/providers的内容如何,例如myApp.value('clientId', 'a12345654321x');在路线之间是否也持续存在?
Bndr

@TheBndr:应该的。就我所知,价值只是一种特殊的服务形式。
罗伯特·科里特尼克

3
如果您重新加载页面,服务将不会保留数据。因此,如果您位于表单的第4页并重新加载该页面,则将丢失所有填充的数据。
danielrvt 2014年

1
好答案!附带说一句,对于那些接受此答案的服务的样式指南-本身不是构造函数(即用作新的XX)的服务应命名为小写骆驼:github.com/mgechev/angularjs-style-guide
马特·伯恩

9

该服务将起作用,但是仅使用普通作用域和控制器来完成此服务的逻辑方法是设置控制器和元素,以使其反映模型的结构。特别是,您需要一个父元素和一个建立父作用域的控制器。表单的各个页面应位于作为父级的子级的视图中。即使更新子视图,父范围也将保留。

我假设您正在使用ui-router,因此可以嵌套嵌套的命名视图。然后用伪代码:

<div ng-controller="WizardController">
  <div name="stepView" ui-view/>
</div>

然后,WizardController定义您要在多页表单的各个步骤中保留的范围变量(我将其称为“向导”)。然后,您的路线只会更新stepView。每个步骤可以具有自己的模板,控制器和范围,但是它们的范围在页面之间丢失。但是WizardController中的作用域保留在所有页面中。

要从子控制器更新WizardController范围,您将需要使用类似语法$scope.$parent.myProp = 'value'setMyProp在WizardController上为每个范围变量定义一个函数。否则,如果您尝试直接从子控制器设置父作用域变量,则最终只会在子项本身上创建一个新的作用域变量,从而遮盖父变量。

有点难以解释,对于缺乏完整的示例,我深表歉意。基本上,您需要一个父控制器来建立一个父作用域,该作用域将保留在表单的所有页面中。


1
可以与ui-router一起使用yes(这是设计这样的页面的一种非常不错的方法),但是不是开箱即用的。开箱即用的服务方法是必经之路。
Erik Honn 2014年

1
为了澄清起见,父作用域属性将始终由子作用域继承。但是,如果要从子作用域设置父作用域属性,则需要在父作用域上访问它,否则,您将在子作用域上创建同名的新属性。可以通过以下操作来设置父范围属性:$scope.$parent.myProp = 'hello world';
mbursill 2014年

1
这是比使用服务更好的方法。服务是单例,因此定义的任何状态对于应用程序都是全局的。如果用户在整个过程中退出向导,然后重新启动它,则上次运行时服务中将存在剩余状态-除非您确保在每个退出点都正确清理了该服务,但这可以容易成为大量维修头痛!
丹金

更热衷于此答案
Kurai Bankusu '17

如果您不使用Angular UI Router,首先要想到的就是服务。但是,如果使用的是UI Router,则它具有嵌套的解析程序,可以在嵌套视图之间保留信息。我认为这比尝试访问父范围更干净。medium.com/opinionated-angularjs/…–
losmescaleros

5

数据可以通过两种方式在控制器之间传递

  1. $rootScope
  2. 模型

下面的示例演示了使用模型传递值

app.js

angular.module('testApp')
  .controller('Controller', Controller)
  .controller('ControllerTwo', ControllerTwo)
  .factory('SharedService', SharedService);

SharedService.js

function SharedService($rootScope){

 return{
    objA: "value1",
    objB: "value2"
  }
}

//修改控制器A中的值

Controller.js

function Controller($scope, SharedService){

 $scope.SharedService = SharedService;

 $scope.SharedService.objA = "value1 modified";
}

//访问controllertwo中的值

ControllerTwo.js

function ControllerTwo($scope, SharedService){

 $scope.SharedService = SharedService;

 console.log("$scope.SharedService.objA"+$scope.SharedService.objA); // Prints "value1 modified"
}

希望这可以帮助。

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.