2013-09-26 182 views
80

Làm thế nào để gọi một phương thức được xác định trong phạm vi con từ phạm vi cha mẹ của nó?angularJS: Cách gọi hàm phạm vi con trong phạm vi cha mẹ

function ParentCntl() { 
    // I want to call the $scope.get here 
} 

function ChildCntl($scope) { 
    $scope.get = function() { 
     return "LOL";  
    } 
} 

http://jsfiddle.net/wUPdW/

+2

Đặt cược tốt nhất, xác định dịch vụ, đưa dịch vụ đó vào cả hai bộ điều khiển. Hoặc sử dụng rootscope. – tymeJV

Trả lời

126

Bạn có thể sử dụng $broadcast từ cha mẹ cho một đứa trẻ:

function ParentCntl($scope) { 

    $scope.msg = ""; 
    $scope.get = function(){ 
     $scope.$broadcast ('someEvent'); 
     return $scope.msg;   
    } 
} 

function ChildCntl($scope) {    
    $scope.$on('someEvent', function(e) { 
     $scope.$parent.msg = $scope.get();    
    }); 

    $scope.get = function(){ 
     return "LOL";  
    } 
} 

fiddle làm việc: http://jsfiddle.net/wUPdW/2/

CẬP NHẬT: Có phiên bản khác, ít kết và thử nghiệm nhiều hơn:

function ParentCntl($scope) { 
    $scope.msg = ""; 
    $scope.get = function(){ 
     $scope.$broadcast ('someEvent'); 
     return $scope.msg;   
    } 

    $scope.$on('pingBack', function(e,data) { 
     $scope.msg = data;   
    }); 
} 

function ChildCntl($scope) {    
    $scope.$on('someEvent', function(e) { 
     $scope.$emit("pingBack", $scope.get());   
    }); 

    $scope.get = function(){ 
     return "LOL";  
    } 
} 

Fiddle: http://jsfiddle.net/uypo360u/

+0

Thật tuyệt! Nhưng, nếu bạn không (muốn) biết phạm vi của người gọi ở đâu (tôi có nghĩa là trong '$ scope. $ Parent' hoặc trong' $ scope. $ Parent. $ Parent', etc)? Ah, vâng: chuyển một cuộc gọi lại trong các thông số! :) – user2173353

+0

@ user2173353 bạn rất đúng; có một cách khác: '$ emit' từ một đứa trẻ đến một phụ huynh. Tôi nghĩ rằng đó là thời gian để cập nhật câu trả lời của tôi .. – Cherniv

+0

Có ý tưởng hay không khi gọi cho người nghe toàn cầu ở đâu đó, bộ điều khiển con trong trường hợp này? Isnt nó antipattern và khó kiểm tra sau này? Chúng ta không nên dùng thuốc tiêm hay thuốc lá? – calmbird

27

Tôi xin gợi ý một giải pháp khác:

var app = angular.module("myNoteApp", []); 


app.controller("ParentCntl", function($scope) { 
    $scope.obj = {}; 
}); 

app.controller("ChildCntl", function($scope) { 
    $scope.obj.get = function() { 
      return "LOL";  
    }; 
}); 

Ít mã và sử dụng thừa kế nguyên mẫu.

Plunk

+0

Ai đó có thể giải thích nếu cách tiếp cận này tốt hơn cách tiếp cận hướng sự kiện được đề cập ở trên trong trường hợp nào và nếu có, tại sao? nếu bạn có bộ điều khiển con đa cấp lvl w thì sao? sẽ làm việc này nếu obj.get được định nghĩa bên trong một bộ điều khiển con trong một bộ điều khiển con miễn là không có bộ điều khiển có tên chức năng tương tự được xác định? Cảm ơn bạn trước. – ZvKa

+0

Thú vị ... cảm ơn cho nhận xét, những gì ném tôi ra là tôi nghĩ js nguyên mẫu/angularjs phạm vi thừa kế chỉ áp dụng cho một hướng duy nhất .... con -> cha mẹ hoặc con phạm vi -> cha mẹ phạm vi, không phải là cách khác xung quanh .... nhưng tôi đoán tôi đang thiếu một cái gì đó @ _ @ – ZvKa

+1

Hãy để tôi sửa những gì tôi nói mà không phải là hoàn toàn đúng sự thật. Bạn đúng trong những gì bạn đã nói: thừa kế phạm vi chỉ được áp dụng cho một hướng duy nhất .... con -> cấp độ gốc. Điều thực sự xảy ra ở đây là nếu bạn định nghĩa $ scope.get trong phạm vi con, 'get' sẽ được định nghĩa chỉ trên phạm vi con (Đôi khi được gọi là định nghĩa nguyên thủy). Nhưng khi bạn định nghĩa $ scope.obj.get, thì phạm vi con sẽ tìm kiếm obj được định nghĩa trên phạm vi cha mẹ, là thứ bậc phân cấp. – Canttouchit

9

Đăng ký chức năng của trẻ khi cha mẹ khởi tạo. Tôi đã sử dụng ký hiệu "làm" để rõ ràng trong mẫu.

MẪU

<div ng-controller="ParentCntl as p"> 
    <div ng-controller="ChildCntl as c" ng-init="p.init(c.get)"></div> 
</div> 

KIỂM SOÁT

... 
function ParentCntl() { 
    var p = this; 
    p.init = function(fnToRegister) { 
    p.childGet = fnToRegister; 
    }; 
// call p.childGet when you want 
} 

function ChildCntl() { 
    var c = this; 
    c.get = function() { 
    return "LOL";  
    }; 
} 

"Nhưng", bạn nói, "ng-initisn't supposed to be used this way!". Vâng, vâng, nhưng

  1. tài liệu mà không giải thích lý do tại sao không, và
  2. Tôi không tin rằng các tác giả tài liệu được coi là trường hợp sử dụng ALL có thể cho nó.

Tôi nói đây là cách sử dụng tốt cho nó. Nếu bạn muốn downvote tôi, xin vui lòng bình luận với lý do! :)

Tôi thích cách tiếp cận này vì nó giữ các thành phần mô đun hơn. Các ràng buộc duy nhất là trong các mẫu, và có nghĩa là

  • đứa trẻ điều khiển không cần phải biết gì về những đối tượng để thêm chức năng của nó để (như trong câu trả lời @ canttouchit của)
  • điều khiển cha mẹ có thể sử dụng với bất kỳ kiểm soát trẻ em khác trong đó có một chức năng get
  • không yêu cầu phát sóng, mà sẽ nhận được rất xấu xí trong một ứng dụng lớn, trừ khi bạn kiểm soát chặt chẽ không gian tên sự kiện

cách tiếp cận này tiếp cận gần gũi hơn Tero's idea of modularising with directives (lưu ý trong mô-đun của mình ví dụ ed, contestants được chuyển từ cấp độ gốc sang chỉ mục "con" trong MẪU).

Thực tế giải pháp khác có thể là xem xét việc triển khai ChildCntl làm chỉ thị và sử dụng liên kết & để đăng ký phương thức init.

+1

Tôi biết đây là một bài cũ, nhưng điều này có vẻ như là một ý tưởng tồi bởi vì phụ huynh có thể giữ một tham chiếu đến đứa trẻ sau khi đứa trẻ bị phá hủy. –