170

我有這個模塊路線:使用時失去範圍NG-包括

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.lineTextundefined,這可以通過將ng-controller="HomeCtrl"添加到partial1.html來解決,但它會導致控制器被調用兩次。我在這裏錯過了什麼?

回答

76

這是因爲ng-include它創建一個新的子範圍,所以$scope.lineText不會更改。我認爲this是指當前範圍,所以應該設置this.lineText

247

作爲@Renan提到,ng-include創建一個新的子範圍。這個範圍從HomeCtrl範圍原型繼承(見下面的虛線)。 ng-model="lineText"實際上是在子範圍上創建一個原始範圍屬性,而不是HomeCtrl的範圍。這孩子範圍不是父/ HomeCtrl範圍訪問:

ng-include scope

要存儲什麼,用戶鍵入到H​​omeCtrl的$ 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 
    }); 
}; 

Fiddle

備選方案:

  • 限定上HomeCtrl的$範圍的對象屬性,和使用,在所述部分:ng-model="someObj.lineText; fiddle
  • 不推薦,這是更多的黑客:在部分創建/訪問一個lineText屬性的HomeCtrl $ scope:ng-model="$parent.lineText"; fiddle

這是有點麻煩,解釋爲什麼上面的兩個備選方案的工作,但它完全說明如下:What are the nuances of scope prototypal/prototypical inheritance in AngularJS?

我不建議在addLine()函數中使用this。它變得不太清楚哪個範圍被訪問/操縱。

+1

最後我明白了。 – 2013-03-22 03:09:29

+0

我使用了**對象**,但它們的範圍仍然被遮罩。我試過'$ parent.',它運行得很好。你爲什麼認爲這是一個黑客? (我可以看到它會增加維護,如果你重構你的html) – Jess 2013-09-25 16:08:52

+1

@Jess有同樣的問題,爲什麼這被認爲是黑客? – qbert65536 2013-12-20 18:29:26

3

我已經想出瞭如何解決這個問題,而不是混合父和子範圍數據。 在ng-include元素上設置ng-if並將其設置爲範圍變量。 例如:

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

在你的控制器,當您將所有你在子範圍內所需要的數據,然後將秀trueng-include此時將複製範圍內的數據集並將其設置在您的子範圍中。

經驗法則是將範圍數據的範圍縮小得更深,否則就會出現這種情況。

最大

29

而不是使用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

對於任何讀者,他的意思是'$ scope。$ parent'而不是'$ parent'根據Angular未定義。 – Sebastialonso 2015-05-21 20:09:30

+1

這個答案爲我節省了一天!非常感謝您指出使用$ parent。 – 2015-05-31 01:40:16

+0

是$ scope。$ parent通過引用傳遞?或者它只是父母的副本? – OMGPOP 2015-06-25 12:01:53