angleJS: Cách gọi hàm phạm vi con trong phạm vi cha


95

Làm cách nào để gọi một phương thức được định nghĩa trong phạm vi con từ phạm vi cha của nó?

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 một dịch vụ, đưa dịch vụ đó vào cả hai bộ điều khiển. Hoặc sử dụng máy soi rễ.
tymeJV

Câu trả lời:


145

Bạn có thể sử dụng $broadcasttừ cha mẹ đến con cái:

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";    
    }
}

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

CẬP NHẬT : Có một phiên bản khác, ít ghép hơn và dễ kiểm tra 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/


Điều đó khá tuyệt! Nhưng, điều gì sẽ xảy ra nếu bạn không (muốn) biết phạm vi người gọi ở đâu (ý tôi là trong $scope.$parenthoặc trong $scope.$parent.$parent, v.v.)? À, vâng: chuyển lệnh gọi lại trong params! :)
user2173353

@ user2173353 bạn nói rất đúng; còn một cách nữa: $emittừ con thành cha mẹ. tôi nghĩ rằng đó là một thời gian để cập nhật câu trả lời của tôi ..
Cherniv

Có nên gọi đến bộ nghe toàn cầu ở đâu không, bộ điều khiển con trong trường hợp này? Nó không phải là phản vật chất và khó kiểm tra sau này? Chúng ta không nên sử dụng tiêm hoặc smth?
calmbird

@calmbird, mỗi thứ phải được sử dụng cẩn thận, đó là điều chắc chắn .. Một số thích sử dụng các dịch vụ trong những trường hợp tương tự. Dù sao, tôi đã thêm phiên bản tao nhã hơn (mà không gây phiền nhiễu $parent)
Cherniv

9
Cách tiếp cận này là sạch hơn. Chuyển một cuộc gọi lại tại $broadcastvà bạn có thể loại bỏ pingBackhoàn toàn.
cao nhất

34

Hãy để tôi đề xuất 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ã hơn và sử dụng kế thừa nguyên mẫu.

Plunk


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 theo hướng sự kiện được đề cập ở trên trong những trường hợp nào và nếu có thì tại sao? điều gì sẽ xảy ra nếu bạn có nhiều bộ điều khiển con có phân cấp lvl? điều này sẽ hoạt động nếu obj.get được xác định bên trong bộ điều khiển con trong bộ điều khiển con miễn là không có bộ điều khiển nào có cùng tên chức năng được xác định? Cảm ơn bạn trước.
ZvKa

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

3
Điều này sẽ hoạt động như thế nào nếu trẻ có phạm vi cách ly riêng của nó?
Dinesh

2
Câu hỏi không đề cập đến phạm vi cô lập, Tuy nhiên, nếu bạn có phạm vi cô lập, bạn có thể sử dụng ràng buộc phạm vi cô lập. Imo, phát sóng hơi lộn xộn.
Canttouchit

2
Tôi không nghĩ rằng ví dụ này là có thể nếu bạn cần truy cập vào chức năng điều khiển con từ cha mẹ điều khiển , không phải mẫu. Ví dụ này chỉ hoạt động do ràng buộc hai chiều trên mẫu, mà tôi cho rằng sẽ tiếp tục thăm dò cho đến khi $scope.obj.get()là một hàm hợp lệ.
danyim

11

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

BẢN MẪU

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

NGƯỜI ĐIỀU KHIỂN

...
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-init không được sử dụng theo cách này !". Vâng, vâng, nhưng

  1. tài liệu đó không giải thích tại sao không, và
  2. Tôi không tin rằng các tác giả tài liệu đã xem xét TẤT CẢ các trường hợp sử dụng có thể cho nó.

Tôi nói đây là một công dụng tốt cho nó. Nếu bạn muốn downvote tôi, hãy comment với lý do! :)

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

  • Bộ điều khiển con không phải biết bất kỳ điều gì về đối tượng nào để thêm chức năng của nó vào (như trong câu trả lời của @ canttouchit)
  • kiểm soát của cha mẹ có thể được sử dụng với bất kỳ kiểm soát con nào khác có chức năng get
  • không yêu cầu phát sóng, điều này sẽ rất xấu 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 chặt chẽ hơn với ý tưởng của Tero về việc điều biến với các chỉ thị (lưu ý rằng trong ví dụ contestantsđược điều chỉnh của anh ấy, được chuyển từ chỉ thị mẹ sang chỉ thị "con" TRONG TEMPLATE).

Thật vậy, một giải pháp khác có thể là xem xét việc triển khai ChildCntlnhư một chỉ thị và sử dụng &ràng buộc để đăng ký initphương thức.


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

Đây là một giải pháp gọn gàng hơn nhiều so với việc phát sóng các sự kiện. Không hoàn hảo, nhưng tốt hơn. Mặc dù việc dọn dẹp thực sự là một vấn đề.
mcv

-1

Bạn có thể làm cho đối tượng trẻ em.

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


app.controller("ParentCntl", function($scope) {
    $scope.child= {};
    $scope.get = function(){
      return $scope.child.get(); // you can call it. it will return 'LOL'
    }
   // or  you can call it directly like $scope.child.get() once it loaded.
});

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

Ở đây con đang chứng minh đích đến của phương thức get.

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.