ng-includeを使用するとスコープが失われる


181

私はこのモジュールのルートを持っています:

var mainModule = angular.module('lpConnect', []).
    config(['$routeProvider', function ($routeProvider) {
    $routeProvider.
        when('/home', {template:'views/home.html', controller:HomeCtrl}).
        when('/admin', {template:'views/admin.html', controller:AdminCtrl}).
        otherwise({redirectTo:'/connect'});
}]);

ホームHTML:

<div ng-include src="views.partial1"></div>

partial1 HTML:

<form ng-submit="addLine()">
    <input type="text" ng-model="lineText" size="30" placeholder="Type your message here">
</form>

HomeCtrl

function HomeCtrl($scope, $location, $window, $http, Common) {
    ...
    $scope.views = {
        partial1:"views/partial1.html"
    };

    $scope.addLine = function () {
        $scope.chat.addLine($scope.lineText);
        $scope.lines.push({text:$scope.lineText});
        $scope.lineText = "";
    };
...
}

ではaddLine機能が$scope.lineTextありundefined、これは追加することで解決することが可能ng-controller="HomeCtrl"partial1.htmlしかし、それはコントローラが二回と呼ばれるようになり、。ここで何が欠けていますか?

回答:


83

これng-includeにより、新しい子スコープが作成されるため、$scope.lineText変更されません。そうだと思いますthisは現在のスコープ参照してとので、this.lineText設定する必要があります。


260

@Renanが述べたように、ng-includeは新しい子スコープを作成します。このスコープは、典型的にはHomeCtrlスコープから継承します(以下の破線を参照)。 ng-model="lineText"実際には、HomeCtrlのスコープではなく、子スコープにプリミティブスコーププロパティを作成します。この子スコープには、parent / HomeCtrlスコープからアクセスできません。

ng-includeスコープ

ユーザーがHomeCtrlの$ scope.lines配列に入力した内容を保存するには、値をaddLine関数に渡すことをお勧めします。

 <form ng-submit="addLine(lineText)">

さらに、lineTextはngIncludeスコープ/パーシャルによって所有されているため、それをクリアする責任があると思います。

 <form ng-submit="addLine(lineText); lineText=''">

したがって、関数addLine()は次のようになります。

$scope.addLine = function(lineText) {
    $scope.chat.addLine(lineText);
    $scope.lines.push({
        text: lineText
    });
};

フィドル

代替案:

  • HomeCtrlの$ scopeでオブジェクトプロパティを定義し、それをパーシャルで使用しng-model="someObj.lineTextます。バイオリン
  • 推奨されません。これはハックの詳細ですlineText。HomeCtrl$ scope:のプロパティ   を作成/アクセスするには、パーシャルで$ parentを使用しますng-model="$parent.lineText"バイオリン

上記の2つの選択肢が機能する理由を説明するのは少し複雑ですが、ここで完全に説明されています。

thisaddLine()関数での使用はお勧めしません。どのスコープがアクセス/操作されているかは、はるかに明確ではなくなります。


1
最後に理解しました。
Scott Tesler 2013年

1
@ジェスと同じ質問、なぜこれはハックと見なされますか?
qbert65536 2013

13
@ qbert65536、それは本質的にハック/壊れやすいです。なぜなら、HTMLを再構築すると、もう機能しない可能性があるからです。たとえば、$parent.$parent...それを機能させるためにを使用する必要があるかもしれません。別の言い方を$parentすると、を使用すると、DOM構造に関する仮定が行われます。
Mark Rajcok、2013

6
上記の@Jessのリンクは、この理解スコープngIncludeに変更されました。ページ全体をお読みください。
mraaroncruz 14年

1
これは非常に詳細な回答ですが、すべてを試しましたが成功しませんでした。コントローラへの入力を含むフォームがあり、コントローラの結果を別のdivで表示する必要があります。入力を入力すると、同期が失われ、アプリの実行中にビューdivに0.00の値が一定になります。
zahra 2016年

33

代わりに使用してのthis受け入れ答えとして、使用することを示唆している$parent代わりに。だからあなたpartial1.htmlにはあなたがいるでしょう:

<form ng-submit="$parent.addLine()">
    <input type="text" ng-model="$parent.lineText" size="30" placeholder="Type your message here">
</form>

スコープng-includeやその他のディレクティブの詳細については、こちらをご覧くださいhttps : //github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include


1
どの読者にとっても、彼はAngularによると未定義$scope.$parent$parentはなく、という意味 です。
Sebastialonso

1
この答えは私のために一日を節約します!$ parentの使用を指摘してくれてありがとう。
デレクウェッブ2015年

$ scope。$ parentは参照渡しですか?またはそれは単なる親のコピーですか?
OMGPOP 2015年

1
@Sebastiallonsoは間違っています。$ scope。$ parent.lineTextは未定義です。$ parent.lineTextは機能しており、this.lineTextまたは単にlineTextも機能しています
OMGPOP

これは$scope.$parent、角度1.3.20で動作します
radtek

4

親とサブスコープのデータを混在させずにこの問題を回避する方法を見つけました。設定するng-if上でng-includeの要素とスコープ変数に設定します。例えば ​​:

<div ng-include="{{ template }}" ng-if="show"/>

コントローラで、必要なすべてのデータをサブスコープで設定したら、showをに設定しtrueます。ng-includeこの時点で、あなたのスコープ内のデータ・セットをコピーして、サブスコープでそれを設定します。

経験則は、スコープデータをスコープの深さまで減らすことです。それ以外の場合は、この状況になります。

マックス


私はこのアプローチを同様の問題に使用していますが、すべてのケースに適しているわけではありません。特に、含まれている要素を非表示にしたくない場合
iSpithash
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.