Функция директивного вызова angularjs, указанная в атрибуте, и передает ей аргумент
Я хочу создать директиву, которая ссылается на атрибут. Атрибут определяет функцию, которая должна быть вызвана в области. Но я также хочу передать аргумент функции, которая определена внутри функции ссылки.
<div my-method='theMethodToBeCalled'></div>
В функции связи я связываюсь с событием jQuery, которое передает аргумент, мне нужно перейти к функции:
app.directive("myMethod",function($parse) {
restrict:'A',
link:function(scope,element,attrs) {
var expressionHandler = $parse(attrs.myMethod);
$(element).on('theEvent',function( e, rowid ) {
id = // some function called to determine id based on rowid
scope.$apply(function() {expressionHandler(id);});
}
}
}
app.controller("myController",function($scope) {
$scope.theMethodToBeCalled = function(id) { alert(id); };
}
Без передачи id я могу заставить его работать, но как только я попытаюсь передать аргумент, функция больше не вызывается
Ответы
Ответ 1
Марко хорошо работает.
В отличие от рекомендуемого способа Angular (как показано treeface plunkr) используется выражение обратного вызова, которое не требует определения выраженияHandler. В примере с шаблоном marko:
В шаблоне
<div my-method="theMethodToBeCalled(myParam)"></div>
В функции директивной ссылки
$(element).click(function( e, rowid ) {
scope.method({myParam: id});
});
У этого есть один недостаток по сравнению с решением marko - при первой загрузке функцияMethodToBeCalled будет вызываться с помощью myParam === undefined.
Рабочий экзамен можно найти на @treeface Plunker
Ответ 2
Просто добавьте некоторую информацию к другим ответам - использование &
- хороший способ, если вам нужна изолированная область.
Основной недостаток решения marko заключается в том, что он заставляет вас создавать изолированную область действия для элемента, но вы можете иметь только один из них в элементе (иначе вы столкнетесь с ошибкой angular: несколько директив [ директива1, директива2] с просьбой об изолированном объеме)
Это означает, что вы:
- не может использовать его в элементе hat имеет изолированную область действия
- не может использовать две директивы с этим решением на одном элементе
Поскольку исходный вопрос использует директиву с restrict:'A'
, обе ситуации могут возникать довольно часто в больших приложениях, и использование изолированной области здесь не является хорошей практикой, а также ненужной. На самом деле у rekna была хорошая интуиция в этом случае, и почти она работала, единственное, что он делал неправильно, - это неправильная функция $parsed (см., Что она возвращает здесь: https://docs.angularjs.org/api/ng/service/$parse).
TL; DR; Исправлен код вопроса
<div my-method='theMethodToBeCalled(id)'></div>
и код
app.directive("myMethod",function($parse) {
restrict:'A',
link:function(scope,element,attrs) {
// here you can parse any attribute (so this could as well be,
// myDirectiveCallback or multiple ones if you need them )
var expressionHandler = $parse(attrs.myMethod);
$(element).on('theEvent',function( e, rowid ) {
calculatedId = // some function called to determine id based on rowid
// HERE: call the parsed function correctly (with scope AND params object)
expressionHandler(scope, {id:calculatedId});
}
}
}
app.controller("myController",function($scope) {
$scope.theMethodToBeCalled = function(id) { alert(id); };
}
Ответ 3
Не зная точно, что вы хотите сделать... но все же здесь возможное решение.
Создайте область с свойством '&' - в локальной области.
Он предоставляет способ выполнения выражения в контексте родительской области "(подробнее см. директивная документация).
Я также заметил, что вы использовали функцию стенографической ссылки и сунули в атрибутах объекта там. Вы не можете этого сделать. Более ясно (imho) просто вернуть объект определения директивы. См. Мой код ниже.
Здесь пример кода и fiddle.
<div ng-app="myApp">
<div ng-controller="myController">
<div my-method='theMethodToBeCalled'>Click me</div>
</div>
</div>
<script>
var app = angular.module('myApp',[]);
app.directive("myMethod",function($parse) {
var directiveDefinitionObject = {
restrict: 'A',
scope: { method:'&myMethod' },
link: function(scope,element,attrs) {
var expressionHandler = scope.method();
var id = "123";
$(element).click(function( e, rowid ) {
expressionHandler(id);
});
}
};
return directiveDefinitionObject;
});
app.controller("myController",function($scope) {
$scope.theMethodToBeCalled = function(id) {
alert(id);
};
});
</script>
Ответ 4
Вы можете создать директиву, которая выполняет вызов функции с параметрами, используя attrName: "&"
для ссылки на выражение во внешней области.
Мы хотим заменить директиву ng-click
на ng-click-x
:
<button ng-click-x="add(a,b)">Add</button>
Если у нас была эта область:
$scope.a = 2;
$scope.b = 2;
$scope.add = function (a, b) {
$scope.result = parseFloat(a) + parseFloat(b);
}
Мы могли бы написать нашу директиву так:
angular.module("ng-click-x", [])
.directive('ngClickX', [function () {
return {
scope: {
// Reference the outer scope
fn: "&ngClickX",
},
restrict: "A",
link: function(scope, elem) {
function callFn () {
scope.$apply(scope.fn());
}
elem[0].addEventListener('click', callFn);
}
};
}]);
Вот живая демонстрация:
http://plnkr.co/edit/4QOGLD?p=info
Ответ 5
Вот что сработало для меня.
Html с использованием директивы
<tr orderitemdirective remove="vm.removeOrderItem(orderItem)" order-item="orderitem"></tr>
Html директивы: orderitem.directive.html
<md-button type="submit" ng-click="remove({orderItem:orderItem})">
(...)
</md-button>
Область действия директивы:
scope: {
orderItem: '=',
remove: "&",
Ответ 6
Мое решение:
- на полимере поднять событие (например,
complete
)
- определить директиву, связывающую событие с функцией управления
Директива
/*global define */
define(['angular', './my-module'], function(angular, directives) {
'use strict';
directives.directive('polimerBinding', ['$compile', function($compile) {
return {
restrict: 'A',
scope: {
method:'&polimerBinding'
},
link : function(scope, element, attrs) {
var el = element[0];
var expressionHandler = scope.method();
var siemEvent = attrs['polimerEvent'];
if (!siemEvent) {
siemEvent = 'complete';
}
el.addEventListener(siemEvent, function (e, options) {
expressionHandler(e.detail);
})
}
};
}]);
});
Полимерный компонент
<dom-module id="search">
<template>
<h3>Search</h3>
<div class="input-group">
<textarea placeholder="search by expression (eg. temperature>100)"
rows="10" cols="100" value="{{text::input}}"></textarea>
<p>
<button id="button" class="btn input-group__addon">Search</button>
</p>
</div>
</template>
<script>
Polymer({
is: 'search',
properties: {
text: {
type: String,
notify: true
},
},
regularSearch: function(e) {
console.log(this.range);
this.fire('complete', {'text': this.text});
},
listeners: {
'button.click': 'regularSearch',
}
});
</script>
</dom-module>
Страница
<search id="search" polimer-binding="searchData"
siem-event="complete" range="{{range}}"></siem-search>
searchData
- управляющая функция
$scope.searchData = function(searchObject) {
alert('searchData '+ searchObject.text + ' ' + searchObject.range);
}
Ответ 7
Это должно работать.
<div my-method='theMethodToBeCalled'></div>
app.directive("myMethod",function($parse) {
restrict:'A',
scope: {theMethodToBeCalled: "="}
link:function(scope,element,attrs) {
$(element).on('theEvent',function( e, rowid ) {
id = // some function called to determine id based on rowid
scope.theMethodToBeCalled(id);
}
}
}
app.controller("myController",function($scope) {
$scope.theMethodToBeCalled = function(id) { alert(id); };
}