Angularjs、ルート間でスコープを渡す


87

フォームが複数のページにまたがる状況にあります(理想的ではないかもしれませんが、それはそのようです)。フォーム全体に1つのスコープを設定し、ユーザーが手順に沿って前後に移動すると、状態を簡単に覚えられるようにします。

だから私は非常に疑似コードでやる必要があります:

  1. セットする $scope.val = <Some dynamic data>
  2. リンクをクリックすると、新しいテンプレートにルーティングされます(おそらく同じコントローラーを使用します)。
  3. $scope.val 最後のページと同じ値である必要があります。

どういうわけか、スコープのデータを永続化することは、これについて正しい方法ですか、それとも他の方法がありますか?もちろん、データベースに保存する以外は、ルート間でスコープが永続化されているコントローラーを作成することもできます。


ちょうどganarajへの追加として:ここには、さまざまなコントローラーを通信させる方法に関するスクリーンキャストを含む、本当に素晴らしいブログエントリがあります。また、いじくり回すのに役立つjsfiddleがいくつかあります。onehungrymind.com/angularjs-communicating-between-controllersお役に立てば幸いです。
F Lekschas

回答:


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
ああ!以前はそれを試しましたが、両方のルートに同じコントローラを使用したため、機能しませんでした。そのため、新しいルートごとに、デフォルト値によって前のページで入力した値が上書きされます。2つのコントローラーがある場合、またはデフォルト値がない場合、これは発生しなくなりました。ありがとう!
Erik Honn

1
Value Recipe docs.angularjs.org/guide/providersについてはどうですか、myApp.value('clientId', 'a12345654321x');それはルート間でも永続的ですか?
Bndr

@TheBndr:そうなるはずです。価値観は、私が理解しているように、単なる特別なサービス形態です。
Robert Koritnik 2014

3
ページをリロードすると、サービスはデータを保持しません...したがって、フォームのページ4にいて、そのページをリロードすると、入力されたデータがすべて失われます。
danielrvt 2014

1
素敵な答え!余談ですが、この回答を受け取る人のためのスタイルガイド-それ自体がコンストラクタではない(つまり、新しいXXとして使用される)サービスは、小文字のキャメルという名前にする必要があります:github.com/mgechev/angularjs-style-guide
Matt Byrne、2014年

9

サービスは機能しますが、通常のスコープとコントローラーのみを使用してそれを行う論理的な方法は、モデルの構造を反映するようにコントローラーと要素を設定することです。特に、親スコープを確立する親要素とコントローラーが必要です。フォームの個々のページは、親の子であるビューに存在する必要があります。子ビューが更新されても、親スコープは存続します。

名前付きビューをネストできるように、ui-routerを使用していると思います。次に、疑似コードで:

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

次に、WizardControllerは、マルチページフォームのステップ全体で保持するスコープ変数を定義します(これを「ウィザード」と呼びます)。その後、ルートstepViewのみが更新されます。各ステップには独自のテンプレート、コントローラー、およびスコープを設定できますが、それらのスコープはページごとに失われます。ただし、WizardControllerのスコープはすべてのページで保持されます。

子コントローラーからWizardControllerスコープを更新するには、各スコープ変数に対してWizardControllerのような構文を使用する$scope.$parent.myProp = 'value'か、関数setMyPropを定義する必要があります。そうしないと、子スコープから直接親スコープ変数を設定しようとすると、子自体に新しいスコープ変数が作成され、親変数が隠されてしまいます。

説明するのが難しいので、完全な例がないことをお詫びします。基本的には、フォームのすべてのページで保持される親スコープを確立する親コントローラーが必要です。


1
これはui-routerで動作します(そして、そのようなページをデザインするためのかなり良い方法です)が、そのままでは機能しません。箱から出してすぐにサービスメソッドを選択できます。
エリックホン2014年

1
明確にするために、親スコープのプロパティは常に子スコープに継承されます。ただし、子スコープから親スコーププロパティを設定する場合は、親でアクセスする必要があります。そうでない場合は、子スコープで同じ名前の新しいプロパティを作成します。:親スコープのプロパティを設定することは行くことによって行うことができます$scope.$parent.myProp = 'hello world';
mbursill

1
これは、サービスを使用するよりもはるかに優れたアプローチです。サービスはシングルトンであるため、そこで定義された状態はすべてアプリケーションに対してグローバルです。ユーザーが途中でウィザードを終了してから再起動すると、前回の実行からのサービスが残った状態になります-すべての終了ポイントでサービスを適切にクリーンアップしていることを確認しない限り、これはかなり可能です簡単に実質的なメンテナンスの頭痛になる!
Dan King

この答えにかなり熱心
倉井バンクス2017年

Angular UIルーターを使用していない場合は、サービスが最初に思い浮かびます。ただし、UIルーターを使用している場合は、入れ子になったビュー間で情報を保持できる入れ子になった解決があります。親スコープにアクセスしようとするよりもクリーンなアプローチだと思います。medium.com/opinionated-angularjs/...
losmescaleros

5

2つの方法でコントローラー間でデータを渡すことができます

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

お役に立てれば。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.