170

Tôi có module này các tuyến đường:Mất phạm vi khi sử dụng ng-bao gồm

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

Home 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 chức năng addLine$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?

Trả lời

76

Điều này là do ng-include tạo phạm vi con mới, vì vậy $scope.lineText không thay đổi. Tôi nghĩ rằng this đề cập đến phạm vi hiện tại, vì vậy, nên đặt this.lineText.

247

Như @Renan đã đề cập, ng-include tạo ra phạm vi con mới. Phạm vi này nguyên mẫu thừa hưởng (xem các đường đứt nét bên dưới) từ phạm vi HomeCtrl. ng-model="lineText" thực sự tạo 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 đứa trẻ này không thể truy cập đến phạm vi phụ huynh/HomeCtrl:

ng-include scope

Để lưu trữ những gì người dùng gõ vào $ scope.lines mảng HomeCtrl, tôi đề nghị bạn vượt qua giá trị cho các chức năng addLine:

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

Bên cạnh đó, kể từ lineText được sở hữu bởi phạm vi ngInclude/một phần, tôi cảm thấy nó phải có trách nhiệm thanh toán bù trừ nó:

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

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

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

Fiddle.

Alternatives:

  • xác định một tài sản đối tượng trên phạm vi $ HomeCtrl, và sử dụng trong một phần: ng-model="someObj.lineText; fiddle
  • không được khuyến nghị, đây là phần mềm hack: sử dụng $ parent ở phần để tạo/truy cập thuộc tính lineText trên phạm vi HomeCtrl $: ng-model="$parent.lineText"; fiddle

Nó là một chút liên quan để giải thích lý do tại sao hai phương án trên hoạt động, nhưng nó được giải thích đầy đủ ở đây: What are the nuances of scope prototypal/prototypical inheritance in AngularJS?

tôi không khuyên bạn sử dụng this trong addLine() chức năng. 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 hiểu. –

+0

Tôi đã sử dụng ** đối tượng **, nhưng phạm vi của chúng vẫn bị che khuất. Tôi đã thử '$ parent.' và nó hoạt động rất tốt. Tại sao bạn coi nó là một hack? (Tôi có thể thấy nó sẽ bổ sung bảo trì nếu bạn đã cấu trúc lại mã html của mình) – Jess

+1

Cùng một câu hỏi @Jess có, tại sao đây lại bị coi là hack? – qbert65536

3

Tôi đã tìm ra cách giải quyết vấn đề này mà không cần trộn dữ liệu phụ huynh và phạm vi phụ. Đặt ng-if trên phần tử ng-include và đặt thành biến phạm vi. Ví dụ:

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

Trong điều khiển của bạn, khi bạn đã thiết lập tất cả các dữ liệu bạn cần trong phạm vi tiểu của bạn, sau đó thiết lập chương trình để true. ng-include sẽ sao chép vào thời điểm này tập dữ liệu trong phạm vi của bạn và đặt nó trong phạm vi phụ của bạn.

Quy 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 có tình huống này.

Max

29

Thay vì sử dụng this là câu trả lời chấp nhận đề nghị, sử dụng $parent để thay thế. Vì vậy, trong bạn partial1.html bạ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-include hoặc chỉ thị khác, kiểm tra này: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include

+1

Đối với bất kỳ người đọc nào, anh ta có nghĩa là '$ scope. $ Parent' thay vì' $ parent' là không xác định theo Angular. – Sebastialonso

+1

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

+0

là phạm vi $. $ Parent pass by reference? hoặc nó chỉ là một bản sao của cha mẹ? – OMGPOP

Các vấn đề liên quan