AngularJS - truyền chức năng cho chỉ thị


160

Tôi có một ví dụ angularJS

<div ng-controller="testCtrl">

<test color1="color1" updateFn="updateFn()"></test>
</div>
 <script>
  angular.module('dr', [])
.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function() {
        alert('123');
    }
})
.directive('test', function() {
    return {
        restrict: 'E',
        scope: {color1: '=',
                updateFn: '&'},
        template: "<button ng-click='updateFn()'>Click</button>",
        replace: true,
        link: function(scope, elm, attrs) { 
        }
    }
});

</script>
</body>

</html>

Tôi muốn khi tôi nhấp vào nút, hộp cảnh báo sẽ xuất hiện, nhưng không có gì hiển thị.

Ai giúp tôi với?

Câu trả lời:


243

Để gọi một hàm điều khiển trong phạm vi cha từ bên trong một lệnh phạm vi cô lập, hãy sử dụng dash-separatedtên thuộc tính trong HTML như OP đã nói.

Ngoài ra nếu bạn muốn gửi một tham số cho hàm của mình, hãy gọi hàm bằng cách truyền một đối tượng:

<test color1="color1" update-fn="updateFn(msg)"></test>

Mã não

var app = angular.module('dr', []);

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='updateFn({msg : \"Hello World!\"})'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {             
        }
    }
});

Fiddle


1
Cảm ơn Codezilla vì câu trả lời của bạn và tôi muốn hỏi về trường hợp khi tôi muốn liên kết chức năng "updateFn" từ phạm vi cha mẹ để tách phạm vi trong "kiểm tra" chỉ thị, điều đó có khả thi không?
dùng2707026

2
Các replacethuộc tính đã bị phản đối AngularJS: stackoverflow.com/questions/24194972/...
cdmckay

8
đối với một số lý do đối số là không xác định cho tôi.
chovy

1
@chovy Tôi nghĩ rằng đối số chỉ được sử dụng khi bạn gọi lại phương thức? Việc sử dụng khung mở đầu tiên dường như là định dạng mà góc muốn cho phương thức vừa được thông qua, nhưng tôi có thể sai ở đó
marksyzm

1
Ánh xạ đối tượng updateFn({msg: 'my message'});phải được sử dụng theo định dạng đó khi thực hiện chức năng gọi bên trong linkchức năng của lệnh.
Brian

159

Có lẽ tôi đang thiếu một cái gì đó, nhưng mặc dù các giải pháp khác gọi hàm phạm vi cha, không có khả năng truyền đối số từ mã lệnh, ví dụ , điều này là do update-fnđang gọi updateFn()với các tham số cố định {msg: "Hello World"}. Một thay đổi nhỏ cho phép chỉ thị vượt qua các đối số, mà tôi nghĩ là hữu ích hơn nhiều.

<test color1="color1" update-fn="updateFn"></test>

Lưu ý rằng HTML đang truyền tham chiếu hàm, tức là không có () dấu ngoặc.

Mã não

var app = angular.module('dr', []);

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='callUpdate()'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {       
          scope.callUpdate = function() {
            scope.updateFn()("Directive Args");
          }
        }
    }
});

Vì vậy, ở trên, HTML đang gọi phạm vi cục bộ callUpdate hàm , sau đó 'tìm nạp' updateFn từ phạm vi cha và gọi hàm trả về với các tham số mà lệnh có thể tạo.

http://jsfiddle.net/mygknek2/


9
Không chắc chắn làm thế nào tôi có thể bỏ phiếu xuống cho một cái gì đó hoạt động ?? Bạn nên để lại một bình luận nếu đi xuống bỏ phiếu.
steve

7
Điều này làm việc cho tôi. Nếu bạn không muốn chức năng bổ sung, hãy viếtng-click="updateFn()('Directive Args')"
Graham Walters

7
Ồ scope.updateFn () ("Đối số chỉ thị"); !! KHÔNG scope.updateFn ("Đối số chỉ thị"); !!!
Phụng D. An

2
Đây là câu trả lời hoàn hảo hơn thực sự !!
vinesh

11
@ Ludwik11 chắc chắn - bởi vì scope.updateFn khi được định nghĩa như thế này là một hàm trả về một hàm (do đó () ()) và điều này là do chúng ta chuyển vào phạm vi (thông qua update-fn = "updateFn" trong html) đến chức năng mà chúng ta muốn gọi. 1st () là một lệnh gọi góc để trả về tham chiếu này, 2nd () thực hiện cuộc gọi đến hàm của chúng ta và là nơi chúng ta chuyển bất kỳ tham số nào. HTH
steve

39

Trong thẻ Html chỉ thị 'test' của bạn, tên thuộc tính của hàm không được camelCase, mà dựa trên dấu gạch ngang.

vì vậy - thay vì:

<test color1="color1" updateFn="updateFn()"></test>

viết:

<test color1="color1" update-fn="updateFn()"></test>

Đây là cách của góc để nói sự khác biệt giữa các thuộc tính chỉ thị (chẳng hạn như hàm update-fn) và các hàm.


1
cảm ơn vì đã bắt Tôi đã bao gồm điều đó trong câu trả lời của tôi. Bỏ phiếu lên! :)
Luôn luôn học hỏi

10

Làm thế nào về việc vượt qua chức năng điều khiển với ràng buộc hai chiều ? Sau đó, bạn có thể sử dụng nó trong chỉ thị chính xác giống như trong một mẫu thông thường (Tôi đã loại bỏ các phần không liên quan để đơn giản):

<div ng-controller="testCtrl">

   <!-- pass the function with no arguments -->
   <test color1="color1" update-fn="updateFn"></test>
</div>

<script>
   angular.module('dr', [])
   .controller("testCtrl", function($scope) {
      $scope.updateFn = function(msg) {
         alert(msg);
      }
   })
   .directive('test', function() {
      return {
         scope: {
            updateFn: '=' // '=' bidirectional binding
         },
         template: "<button ng-click='updateFn(1337)'>Click</button>"
      }
   });
</script>

Tôi đáp xuống câu hỏi này, vì tôi đã thử phương pháp trên befire, nhưng bằng cách nào đó nó không hoạt động. Bây giờ nó hoạt động hoàn hảo.


5

sử dụng dấu gạch ngang và chữ thường cho tên thuộc tính (như các câu trả lời khác đã nói):

 <test color1="color1" update-fn="updateFn()"></test>

Và sử dụng "=" thay vì "&" trong phạm vi chỉ thị:

 scope: { updateFn: '='}

Sau đó, bạn có thể sử dụng updateFn như bất kỳ chức năng nào khác:

 <button ng-click='updateFn()'>Click</button>

Có bạn đi!


5
Tại sao bạn lại sử dụng '=' thay vì '&'? Khi tôi thử nó, nó liên tục gọi chức năng của tôi.
1012500

2
Thật sai khi sử dụng '=' cho việc này. Đó là cho hai cách ràng buộc đối tượng.
Ben Taliadoros

1
Tôi nghĩ, vấn đề duy nhất là việc sử dụng dấu ngoặc đơn trong mẫu đầu tiên. Điều này thực thi chức năng sau đó liên kết kết quả. Thay vào đó, bạn chỉ nên chuyển tên của hàm, như thế này:update-fn="updateFn"
Márton Tamás

1
Câu trả lời không hay. rất tệ.
kéo xe

4

Tôi đã phải sử dụng liên kết "=" thay vì "&" vì điều đó không hoạt động. Hành vi kỳ lạ.


2
Điều này là do rất có thể bạn đang chuyển lệnh tham chiếu hàm JS thay vì thực thi. Khi bạn truyền hàm dưới dạng đối số cho lệnh, update-fn="updateFn()"bạn phải bao gồm dấu ngoặc đơn (và có thể là params). Vượt qua nó như một tài liệu tham khảo chức năng update-fn="updateFn"sẽ không hoạt động với &ràng buộc
JorgeGRC

0

@JorgeGRC Cảm ơn câu trả lời của bạn. Mặc dù vậy, một điều "có thể" là rất quan trọng. Nếu bạn có (các) tham số, bạn cũng phải đưa nó vào mẫu của mình và chắc chắn chỉ định địa phương của bạn, vd updateFn({msg: "Directive Args"}.

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.