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" з батьківською областю, щоб ізолювати область в директиві "test", чи це можливо?
user2707026

2
replaceАтрибут застарів в AngularJS: stackoverflow.com/questions/24194972 / ...
cdmckay

8
чомусь аргумент для мене не визначений.
chovy

1
@chovy Я думаю, що аргумент використовується лише після того, як ви знову викликаєте метод? Першим відкритим використанням дужок здається той формат, який
потрібен

1
Відображення об'єктів updateFn({msg: 'my message'});має використовуватися в такому форматі під час виклику функції всередині функції директиви link.
Брайан

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
Не впевнений, як я можу отримати голосування за те, що працює ?? Ви можете залишити коментар, якщо будете голосувати проти.
steve

7
Це працювало для мене. Якщо ви не хочете додаткової функції, просто напишітьng-click="updateFn()('Directive Args')"
Грем Уолтерс

7
Awwww! domain.updateFn () ("Директиви Args"); !! NOT range.updateFn ("Директиви Args"); !!!
Пхунг Д.

2
Це справді більш досконала відповідь !!
vinesh

11
@ Ludwik11 впевнений - це тому, що obseg.updateFn, коли визначено так, це функція, яка повертає функцію (звідси () ()), і це тому, що ми переходимо в область застосування (через update-fn = "updateFn" в html) посилання до функції, яку ми хочемо викликати. 1-й () - це заклик до кута, щоб повернути цю посилання, 2-й () робить виклик нашої функції і знаходиться там, де ми передаємо будь-які параметри. HTH
steve

39

У вашій тезі Html директива 'test', назва атрибута функції не повинна бути camelCrozen, а на основі тире.

так - замість:

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

написати:

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

Це кутовий спосіб визначити різницю між атрибутами директиви (такими як функція update-fn) та функціями.


1
дякую за улов. Я це включив у свою відповідь. Проголосували! :)
ЗавждиAngerner

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>

Я приземлився на це питання, тому що я спробував метод вище befire, але якось не вийшло. Зараз це прекрасно працює.


5

використовувати тире та малі регістри для атрибутів (як і інші відповіді):

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

І використовуйте "=" замість "&" в області директив:

 scope: { updateFn: '='}

Тоді ви можете використовувати updateFn, як і будь-яку іншу функцію:

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

Ось так!


5
Чому б ви використовували '=' замість '&'? коли я спробував це, він постійно повторював свою функцію.
user1012500

2
Неправильно використовувати для цього '='. Це стосується двостороннього прив'язки об'єкта.
Бен Таліадорос

1
Я думаю, єдина проблема - це використання дужок у першому шаблоні. Це виконує функцію, а потім прив'язує результат. Натомість вам слід ввести лише ім’я функції, наприклад:update-fn="updateFn"
Márton Tamás,

1
Погана відповідь. дуже погано.
буксирування

4

Мені довелося використовувати прив'язку "=" замість "&", тому що це не працює. Дивна поведінка.


2
Це тому, що ви, швидше за все, передаєте директиві посилання на функцію JS замість виконання. Коли ви передаєте функцію в якості аргументу директиві, update-fn="updateFn()"ви повинні включити дужки (а може бути і параметри). Передати його як функцію посилання update-fn="updateFn"не буде працювати з &прив'язкою
JorgeGRC

0

@JorgeGRC Дякуємо за вашу відповідь. Одне, однак, "можливо" частина є дуже важливою. Якщо у вас є параметри, ви повинні також включити їх / їх у свій шаблон і обов'язково вказати місцевих жителів, наприклад updateFn({msg: "Directive Args"}.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.