angularjs directive - personalizadas - la función de llamada de directiva angularjs se especifica en el atributo y le pasa un argumento
directive controller angular (7)
Quiero crear una directiva que se vincule con un atributo. El atributo especifica la función que debe invocarse en el alcance. Pero también quiero pasar un argumento a la función que se determina dentro de la función de enlace.
<div my-method=''theMethodToBeCalled''></div>
En la función de enlace me enlace a un evento jQuery, que pasa un argumento que necesito pasar a la función:
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); };
}
Sin pasar la identificación puedo hacer que funcione, pero tan pronto como intento pasar una discusión, la función ya no se llama
Esto debería funcionar.
<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); };
}
Esto es lo que funcionó para mí.
HTML utilizando la directiva
<tr orderitemdirective remove="vm.removeOrderItem(orderItem)" order-item="orderitem"></tr>
Html de la directiva: orderitem.directive.html
<md-button type="submit" ng-click="remove({orderItem:orderItem})">
(...)
</md-button>
Alcance de la directiva:
scope: {
orderItem: ''='',
remove: "&",
La solución de Marko funciona bien .
Para contrastar con la forma angular recomendada (como se muestra por el plunkr de treeface) es usar una expresión de devolución de llamada que no requiere la definición de expressionHandler. En el cambio de ejemplo de marko:
En plantilla
<div my-method="theMethodToBeCalled(myParam)"></div>
En función de enlace directivo
$(element).click(function( e, rowid ) {
scope.method({myParam: id});
});
Esto tiene una desventaja en comparación con la solución de marko: en la primera carga, se invocará la función Method to Be Called con myParam === undefined.
Un examen de trabajo se puede encontrar en @treeface Plunker
Mi solución:
- en polímero plantea un evento (por ejemplo,
complete
) - definir una directiva que vincule el evento a la función de control
Directiva
/*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);
})
}
};
}]);
});
Componente de polímero
<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>
Página
<search id="search" polimer-binding="searchData"
siem-event="complete" range="{{range}}"></siem-search>
searchData
es la función de control
$scope.searchData = function(searchObject) {
alert(''searchData ''+ searchObject.text + '' '' + searchObject.range);
}
Puede crear una directiva que ejecute una llamada a función con params utilizando attrName: "&"
para hacer referencia a la expresión en el ámbito externo.
Queremos reemplazar la directiva ng-click-x
con ng-click-x
:
<button ng-click-x="add(a,b)">Add</button>
Si tuviéramos este alcance:
$scope.a = 2;
$scope.b = 2;
$scope.add = function (a, b) {
$scope.result = parseFloat(a) + parseFloat(b);
}
Podríamos escribir nuestra directiva así:
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);
}
};
}]);
Aquí hay una demostración en vivo: http://plnkr.co/edit/4QOGLD?p=info
Sin saber exactamente lo que quiere hacer ... pero aun así, esta es una posible solución.
Cree un ámbito con una propiedad ''&'' en el ámbito local. "Proporciona una forma de ejecutar una expresión en el contexto del alcance principal" (consulte la documentación de la directiva para obtener más información).
También noté que usaste una función de vinculación abreviada y metiste atributos de objetos allí. No puedes hacer eso. Es más claro (imho) simplemente devolver el objeto de definición de directiva. Ver mi código a continuación.
Aquí hay una muestra de código y un 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>
Solo para agregar algo de información a las otras respuestas, usar &
es una buena forma si necesita un alcance aislado.
La principal desventaja de la solución de marko es que te obliga a crear un alcance aislado en un elemento, pero solo puedes tener uno de esos en un elemento (de lo contrario te encontrarás con un error angular: múltiples directivas [directive1, directive2] pidiendo para alcance aislado )
Esto significa tu :
- no puede usarlo en un elemento que tiene un alcance aislado
- no puede usar dos directivas con esta solución en el mismo elemento
Dado que la pregunta original usa una directiva con restrict:''A''
ambas situaciones pueden surgir bastante a menudo en aplicaciones más grandes, y usar un alcance aislado aquí no es una buena práctica y tampoco es necesaria. De hecho, Rekna tuvo una buena intuición en este caso, y casi lo hizo funcionar, lo único que estaba haciendo mal fue llamar a la función $ analizada incorrectamente (ver lo que aquí se devuelve: https://docs.angularjs.org/api/ng/service/$parse ).
TL; DR; Código de pregunta fijo
<div my-method=''theMethodToBeCalled(id)''></div>
y el código
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); };
}