AngularJS - ฟังก์ชันส่งผ่านไปยังคำสั่ง


160

ฉันมีตัวอย่าง 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>

ฉันต้องการเมื่อฉันคลิกปุ่มกล่องเตือนจะปรากฏขึ้น แต่ไม่มีสิ่งใดแสดง

มีใครช่วยฉันบ้าง

คำตอบ:


243

ในการเรียกใช้ฟังก์ชันคอนโทรลเลอร์ในขอบเขตพาเรนต์จากภายในขอบเขตคำสั่งแบบแยกให้ใช้dash-separatedชื่อแอ็ตทริบิวต์ใน HTML เช่น OP กล่าว

นอกจากนี้หากคุณต้องการส่งพารามิเตอร์ไปยังฟังก์ชันของคุณให้เรียกใช้ฟังก์ชันโดยผ่านวัตถุ:

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

JS

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
ขอบคุณ Codezilla สำหรับคำตอบของคุณและฉันต้องการถามเกี่ยวกับเหตุการณ์ที่เกิดขึ้นเมื่อฉันต้องการผูกฟังก์ชั่น "updateFn" จากขอบเขตหลักเพื่อแยกขอบเขตในคำสั่ง "ทดสอบ" เป็นไปได้ไหม
user2707026

2
replaceแอตทริบิวต์ได้รับการคัดค้านใน AngularJS: stackoverflow.com/questions/24194972/...
cdmckay

8
ด้วยเหตุผลบางอย่างอาร์กิวเมนต์ไม่ได้กำหนดสำหรับฉัน
chovy

1
@chovy ฉันคิดว่าข้อโต้แย้งนี้จะใช้งานได้ก็ต่อเมื่อคุณเรียกใช้เมธอดอีกครั้งหรือไม่ การใช้วงเล็บเหลี่ยมแบบแรกดูเหมือนจะเป็นรูปแบบที่เชิงมุมต้องการวิธีการที่จะผ่าน แต่ฉันอาจจะผิดที่นั่น
markyzm

1
การแมปวัตถุupdateFn({msg: 'my message'});จะต้องใช้ในรูปแบบนั้นเมื่อทำการเรียกฟังก์ชันภายในlinkฟังก์ชันของคำสั่ง
Brian

159

บางทีฉันไม่มีอะไร แต่ถึงแม้ว่าการแก้ปัญหาอื่น ๆ ทำเรียกใช้ฟังก์ชันขอบเขตผู้ปกครองมีความสามารถในการส่งผ่านอาร์กิวเมนต์จากรหัสคำสั่งนี้เป็นเพราะupdate-fnมีการเรียกร้องให้มีพารามิเตอร์คงที่ในตัวอย่างเช่นupdateFn() {msg: "Hello World"}การเปลี่ยนแปลงเล็กน้อยทำให้คำสั่งผ่านการขัดแย้งซึ่งฉันคิดว่ามีประโยชน์มากกว่า

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

โปรดทราบว่า HTML กำลังส่งการอ้างอิงฟังก์ชันเช่นโดยไม่มี()เครื่องหมายวงเล็บ

JS

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

ดังนั้นในข้างต้น HTML กำลังเรียกcallUpdateฟังก์ชั่นขอบเขตท้องถิ่นซึ่ง 'ดึง' updateFn จากขอบเขตหลักและเรียกฟังก์ชั่นกลับมาพร้อมกับพารามิเตอร์ที่คำสั่งสามารถสร้าง

http://jsfiddle.net/mygknek2/


9
ไม่แน่ใจว่าฉันจะลงคะแนนเสียงให้กับสิ่งที่ใช้ได้อย่างไร คุณควรแสดงความคิดเห็นหากจะลงคะแนน
สตีฟ

7
สิ่งนี้ใช้ได้สำหรับฉัน หากคุณไม่ต้องการฟังก์ชั่นพิเศษเพียงเขียนng-click="updateFn()('Directive Args')"
เกรแฮมวอลเตอร์ส

7
โอ้! scope.updateFn () ("Array Directive"); !! NOT scope.updateFn ("Directive Args"); !!!
Phung D.

2
นี่คือคำตอบที่สมบูรณ์แบบมากขึ้นแน่นอน !!
vinesh

11
@ Ludwik11 แน่นอน - เพราะ scope.updateFn เมื่อกำหนดเช่นนี้เป็นฟังก์ชั่นที่ส่งกลับฟังก์ชั่น (ดังนั้น () () ()) และนี่เป็นเพราะเราผ่านเข้าไปในขอบเขต (ผ่าน update-fn = "updateFn" ใน html) การอ้างอิง ฟังก์ชั่นที่เราต้องการเรียกว่า ที่ 1 () คือการเรียกไปที่เชิงมุมเพื่อกลับมาอ้างอิงนี้ที่ 2 () ทำให้การเรียกไปยังฟังก์ชั่นของเราและเป็นที่ที่เราผ่านพารามิเตอร์ใด ๆ HTH
สตีฟ

39

ในแท็กคำสั่ง 'ทดสอบ' ของคุณชื่อแอตทริบิวต์ของฟังก์ชันไม่ควรเป็น camelCased แต่เป็นแบบแดช

ดังนั้น - แทน:

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

เขียน:

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

นี่เป็นวิธีของมุมที่จะบอกความแตกต่างระหว่างแอตทริบิวต์คำสั่ง (เช่นฟังก์ชั่น update-fn) และฟังก์ชั่น


1
ขอบคุณสำหรับการจับ ฉันได้รวมไว้ในคำตอบของฉัน โหวตแล้ว! :)
AlwaysALearner

10

วิธีการเกี่ยวกับการส่งผ่านฟังก์ชั่นการควบคุมด้วยสองทิศทางผูกพัน ? จากนั้นคุณสามารถใช้มันในคำสั่งเหมือนกับในแม่แบบปกติ (ฉันถอดชิ้นส่วนที่ไม่เกี่ยวข้องเพื่อความเรียบง่าย):

<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>

ฉันลงจอดที่คำถามนี้เพราะฉันลองใช้วิธีการด้านบนของไฟ แต่ไม่ได้ผล ตอนนี้มันทำงานได้อย่างสมบูรณ์


5

ใช้เครื่องหมายขีดกลางและตัวพิมพ์เล็กสำหรับชื่อแอตทริบิวต์ (เช่นคำตอบอื่น ๆ ที่กล่าวไว้):

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

และใช้ "=" แทน "&" ในขอบเขต directive:

 scope: { updateFn: '='}

จากนั้นคุณสามารถใช้ updateFn เหมือนฟังก์ชั่นอื่น ๆ :

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

ไปแล้ว!


5
ทำไมคุณถึงใช้ '=' แทนที่จะเป็น '&' เมื่อฉันลองสิ่งนี้มันจะเรียกฟังก์ชั่นของฉันซ้ำ ๆ
user1012500

2
มันผิดที่จะใช้ '=' สำหรับสิ่งนี้ นั่นคือการผูกวัตถุสองทาง
Ben Taliadoros

1
ฉันคิดว่าปัญหาเดียวคือการใช้วงเล็บในแม่แบบแรก นี่เป็นการเรียกใช้ฟังก์ชันจากนั้นจึงผูกผลลัพธ์ แต่คุณควรส่งเฉพาะชื่อของฟังก์ชั่นเช่นนี้:update-fn="updateFn"
MártonTamás

1
คำตอบที่ไม่ดี ที่เลวร้ายมาก.
2560

4

ฉันต้องใช้การผูก "=" แทนที่จะเป็น "&" เพราะนั่นไม่ทำงาน พฤติกรรมแปลก ๆ


2
นี่เป็นเพราะคุณน่าจะผ่านคำสั่งอ้างอิงฟังก์ชัน JS แทนการดำเนินการ เมื่อคุณผ่านฟังก์ชั่นเป็นอาร์กิวเมนต์ไปยังคำสั่งupdate-fn="updateFn()"คุณจะต้องรวมวงเล็บ (และอาจ params) ผ่านมันเป็นฟังก์ชั่นการอ้างอิงupdate-fn="updateFn"จะไม่ทำงานกับการ&ผูก
JorgeGRC

0

@ JorgeGRC ขอบคุณสำหรับคำตอบของคุณ แม้ว่าสิ่งหนึ่งส่วน "บางที" มีความสำคัญมาก หากคุณมีพารามิเตอร์ (s) คุณต้องมีมัน / พวกเขาในแม่แบบของคุณได้เป็นอย่างดีและให้แน่ใจว่าคุณระบุชาวบ้านupdateFn({msg: "Directive Args"}เช่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.