AngularJSの親スコープ変数を更新する


113

2つのコントローラーがあり、1つは別のコントローラーにラップされています。これで、子スコープが親スコープからプロパティを継承することがわかりましたが、親スコープ変数を更新する方法はありますか?これまでのところ、明確な解決策はありません。

私の状況では、フォーム内にカレンダーコントローラがあります。送信時にフォームに開始日と終了日が含まれるように、親スコープ(フォーム)から開始日と終了日を更新したいと思います。


あなたのカレンダーコントローラーはディレクティブであるように聞こえます。
ジョナ

回答:


193

親スコープでオブジェクト(プリミティブではない)を使用する必要がある場合、子スコープから直接更新できます

親:

app.controller('ctrlParent',function($scope){
    $scope.parentprimitive = "someprimitive";
    $scope.parentobj = {};
    $scope.parentobj.parentproperty = "someproperty";
});

子:

app.controller('ctrlChild',function($scope){
    $scope.parentprimitive = "this will NOT modify the parent"; //new child scope variable
    $scope.parentobj.parentproperty = "this WILL modify the parent";
});

作業デモhttp : //jsfiddle.net/sh0ber/xxNxj/

AngularJSのスコーププロトタイプ/プロトタイプ継承のニュアンスは何ですか?を参照してください


1
これを実装しようとすると、「未定義のプロパティ「parentproperty」を設定できません」というエラーが表示されます。
Malcr001 2013年

コードを投稿できますか?フィドルデモで動作しています。カレンダーコントロールが分離スコープを使用する場合、親スコープから継承しないため、ディレクティブのスコープに値を渡す必要があります。
Dan

すみません、この質問を忘れてしまいました。結局、私はこの答えの助けを借りてそれを機能させることができたので、それを受け入れました。
Malcr001 2013年

{{parentobj.parentproperty}}をctrlParent div要素に配置すると、parentobjオブジェクトが宣言され、このオブジェクトがctrlParentスコープにあると設定されます。これは正しい仮定ですか?
ステファン

1
ありがとう、これでうまくいきます!私は間違いなくこれについて読んでおくべきです(典型的な継承とプリミティブ)。SOリンクよりも少し多く説明している読み物をお勧めできますか?
jvannistelrooy 2014

116

このタスクを実行し、$scope.$parent変数を使用しない方法がもう1つあります。

親スコープの値を変更するメソッドを用意し、子スコープで使用するだけです。このような:

app.controller('ctrlParent',function($scope) {
  $scope.simpleValue = 'x';
  $scope.changeSimpleValue = function(newVal) {
    $scope.simpleValue = newVal;
  };
});

app.controller('ctrlChild',function($scope){
    $scope.changeSimpleValue('y');
});

また、機能し、値の変更をより詳細に制御できます。

その後、次のようなHTMLでもメソッドを呼び出すことができます<a ng-click="changeSimpleValue('y')" href="#">click me!</a>


1
良い解決策!これは、現在の$ scopeに何かが見つからない場合、Angularが$ parentを検索するため機能します。docs.angularjs.org/guide/scope(「スコープ階層」を参照)
Elo

私はこの答えが好きです。不要なオブジェクトを作成する必要はありません。
grimmdude 2015

3
今後の読者:これらの5つのコメントはすべて、少し見当違いです。すべての変数に対して2つのセッター関数(「不要なオブジェクト」)を作成することは、継承の不必要で不要な手段であり、Angularの方法ではありません。Angularの作成者であるMisko Heveryは、「ng-modelがあると、どこかにドットがあるはずです。ドットがないと、間違っている」と語ります。 Misko ビデオ @ 29:19
Dan

controllerAS構文を使用してこのソリューションを適用するにはどうすればよいですか?
niran 2018年

6

これも機能します(ただし、これがベストプラクティスに従っているかどうかはわかりません)

app.controller('ctrlParent',function($scope) {
    $scope.simpleValue = 'x';
});

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});

1
正解です。$ scope。$ parent.valueを使用するとほとんどの場合に機能しますが、大規模で複雑なプロジェクトでは管理が難しくなる可能性があるため、通常は広範囲に使用することは最善の方法ではありません。
Alex Johnson

4

スコープにプリミティブ属性を割り当てると、親スコープに同じ名前の属性がある場合でも、スコープに対して常にローカルになります(その場で作成される場合があります)。これは設計上の決定であり、良い選択です。

親スコープ内のいくつかのプリミティブ(int、booleans、string)をビューから変更する必要がある場合、それをそのスコープ内の別のオブジェクトの属性にする必要があるため、割り当ては次のようになります。

<a ng-click="viewData.myAttr = 4">Click me!</a>

そしてそれは順番に:

  1. viewData定義されているスコープからオブジェクトを取得する
  2. そのmyAttr属性に4を割り当てます。

4

親で宣言された変数にアクセスするには、子コントローラーまたはテンプレートファイルで$ parentを使用する必要があります

コントローラ内

$scope.$parent.varaiable_name

HTMLテンプレート

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