使用ng-include时失去范围

时间:2012-07-10 11:31:06

标签: javascript html angularjs angularjs-scope angularjs-ng-include

我有这个模块路线:

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来解决,但是会导致控制器被调用两次。我在这里缺少什么?

4 个答案:

答案 0 :(得分:257)

正如@Renan所提​​到的,ng-include创建了一个新的子范围。此范围从HomeCtrl范围原型继承(参见下面的虚线)。 ng-model="lineText"实际上在子范围上创建了一个原始范围属性,而不是HomeCtrl的范围。父/ HomeCtrl范围无法访问此子范围:

ng-include scope

要存储用户键入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
    });
};

Fiddle

备选方案:

  • 在HomeCtrl的$ scope上定义一个对象属性,并在partial:ng-model="someObj.lineText中使用它; fiddle
  • 不推荐,这更像是一个hack:在partial中使用$ parent来创建/访问HomeCtrl $范围内的lineText属性:ng-model="$parent.lineText"; fiddle

有一点涉及解释为什么上述两种选择有效,但这里有充分说明:What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

我不建议在addLine()函数中使用this。不太清楚哪个范围被访问/操纵。

答案 1 :(得分:81)

这是因为ng-include创建了一个新的子范围,因此$scope.lineText不会更改。我认为this是指当前范围,因此应设置this.lineText

答案 2 :(得分:32)

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

答案 3 :(得分:3)

我已经弄清楚如何在不混合父和子范围数据的情况下解决此问题。 在ng-if元素上设置ng-include并将其设置为范围变量。 例如:

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

在控制器中,当您在子范围中设置了所需的所有数据时,请将show设置为trueng-include此时将复制范围中的数据集,并将其设置在子范围内。

经验法则是缩小范围内的范围数据,否则就会出现这种情况。

最高