Mất phạm vi khi sử dụng ng-bao gồm


181

Tôi có các tuyến mô-đun này:

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'});
}]);

Trang chủ 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 = "";
    };
...
}

Trong addLinehàm $scope.lineTextundefined, điều này có thể được giải quyết bằng cách thêm ng-controller="HomeCtrl"vào partial1.html, tuy nhiên nó làm cho bộ điều khiển được gọi hai lần. Tôi đang thiếu gì ở đây?

Câu trả lời:


83

Điều này là do ng-includetạo ra một phạm vi con mới, do đó $scope.lineTextkhông thay đổi. Tôi nghĩ rằng thisđề cập đến phạm vi hiện tại, vì vậy this.lineTextnên được đặt.


260

Như @Renan đã đề cập, ng-include tạo ra một phạm vi con mới. Phạm vi này kế thừa nguyên mẫu (xem các đường đứt nét bên dưới) từ phạm vi HomeCtrl. ng-model="lineText"thực sự tạo ra một thuộc tính phạm vi nguyên thủy trên phạm vi con, không phải phạm vi của HomeCtrl. Phạm vi con này không thể truy cập được trong phạm vi cha / HomeCtrl:

phạm vi bao gồm

Để lưu trữ những gì người dùng đã nhập vào mảng $ scope.lines của HomeCtrl, tôi khuyên bạn nên chuyển giá trị cho hàm addLine:

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

Ngoài ra, do lineText được sở hữu bởi phạm vi / một phần của ngInclude, tôi cảm thấy cần có trách nhiệm xóa nó:

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

Hàm addLine () do đó sẽ trở thành:

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

Fiddle .

Lựa chọn thay thế:

  • định nghĩa một thuộc tính đối tượng trên phạm vi $ của HomeCtrl và sử dụng thuộc tính đó trong phần : ng-model="someObj.lineText; vĩ cầm
  • không được đề xuất, đây là một vụ hack: sử dụng $ cha mẹ một phần để tạo / truy cập một thuộc lineTexttính trên phạm vi HomeCtrl $ :   ng-model="$parent.lineText"; vĩ cầm

Có một chút liên quan để giải thích tại sao hai lựa chọn thay thế ở trên hoạt động, nhưng nó được giải thích đầy đủ ở đây: các sắc thái của sự thừa kế nguyên mẫu / nguyên mẫu trong AngularJS là gì?

Tôi không khuyên bạn nên sử dụng thishàm addLine (). Nó trở nên ít rõ ràng hơn phạm vi nào đang được truy cập / thao tác.


1
Cuối cùng tôi cũng hiểu.
Scott Tesler

1
Cùng một câu hỏi @Jess đã có, tại sao điều này được coi là một hack?
qbert65536

13
@ qbert65536, về bản chất nó là hack / mong manh vì nếu bạn cấu trúc lại HTML của mình, nó có thể không hoạt động nữa. Ví dụ, sau đó bạn có thể cần phải sử dụng $parent.$parent...để làm cho nó hoạt động. Đặt một cách khác, sử dụng các $parentgiả định về cấu trúc DOM.
Mark Rajcok

6
Liên kết @Jess 'ở trên đã được thay đổi thành Phạm vi Hiểu biết này . Đọc toàn bộ trang, thật tuyệt.
mraaroncruz

1
Đây là một câu trả lời chi tiết tuyệt vời, nhưng tôi đã thử tất cả chúng mà không thành công. Tôi có một biểu mẫu với một số đầu vào cho bộ điều khiển và kết quả của bộ điều khiển nên được xem trên một div khác. Khi tôi nhập bất kỳ đầu vào nào, tính đồng bộ sẽ bị mất và tôi sẽ có giá trị 0,00 không đổi trên div xem trong khi ứng dụng đang chạy.
zahra

33

Thay vì sử dụng thisnhư câu trả lời được chấp nhận, hãy sử dụng $parentthay thế. Vì vậy, trong partial1.htmlbạn sẽ có:

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

Nếu bạn muốn tìm hiểu thêm về phạm vi trong ng-includehoặc các chỉ thị khác, hãy xem phần này: https://github.com/angular/angular.js/wiki/Under Hiểu-Sames # ng-include


1
Đối với bất kỳ độc giả nào, anh ta có nghĩa là $scope.$parentthay vì $parentkhông xác định theo Angular.
Sebastialonso

1
Câu trả lời này tiết kiệm trong ngày cho tôi! Cảm ơn rất nhiều vì đã chỉ ra việc sử dụng $ Parent.
Derek Webb

$ scope. $ Parent vượt qua tham chiếu? hoặc nó chỉ là một bản sao của cha mẹ?
OMGPOP

1
@Sebastiallonso là sai. $ scope. $ Parent.lineText không xác định. $ Parent.lineText đang hoạt động, this.lineText hoặc đơn giản chỉ là lineText cũng đang hoạt động
OMGPOP

$scope.$parenthoạt động với tôi trong góc 1.3,20
radtek

4

Tôi đã tìm ra cách khắc phục vấn đề này mà không trộn lẫn dữ liệu phạm vi phụ và phụ. Đặt a ng-iftrên ng-includephần tử và đặt thành biến phạm vi. Ví dụ :

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

Trong bộ điều khiển của bạn, khi bạn đã đặt tất cả dữ liệu bạn cần trong phạm vi phụ của mình, sau đó đặt hiển thị thành true. Các ng-includesẽ sao chép tại thời điểm này bộ dữ liệu trong phạm vi của bạn và đặt nó trong phạm vi tiểu của bạn.

Nguyên tắc chung là giảm dữ liệu phạm vi sâu hơn phạm vi, nếu không bạn sẽ gặp tình huống này.

Tối đa


Tôi đang sử dụng phương pháp này cho một vấn đề tương tự nhưng nó không phù hợp với mọi trường hợp. Đặc biệt là khi bạn muốn phần tử đi kèm không bao giờ bị ẩn ...
iSpithash
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.