Parece que no puedo encontrar una manera de llamar a una función en el ámbito principal desde una directiva sin utilizar un ámbito aislado. Sé que si uso un alcance aislado, puedo usar "&" en el aislado para acceder a la función en el alcance principal, pero usar un alcance aislado cuando no es necesario tiene consecuencias. Considere el siguiente HTML:
<button ng-hide="hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>
En este ejemplo simple, quiero mostrar un cuadro de diálogo de confirmación de JavaScript y solo llamar a doIt () si hacen clic en "Aceptar" en el cuadro de diálogo de confirmación. Esto es simple usando un alcance aislado. La directiva se vería así:
.directive('confirm', function () {
return {
restrict: 'A',
scope: {
confirm: '@',
confirmAction: '&'
},
link: function (scope, element, attrs) {
element.bind('click', function (e) {
if (confirm(scope.confirm)) {
scope.confirmAction();
}
});
}
};
})
Pero el problema es que, debido a que estoy usando un alcance aislado, ng-hide en el ejemplo anterior ya no se ejecuta en el alcance principal , sino en el alcance aislado (ya que el uso de un alcance aislado en cualquier directiva hace que todas las directivas en ese elemento utilizar el alcance aislado). Aquí hay un jsFiddle del ejemplo anterior donde ng-hide no funciona. (Tenga en cuenta que en este violín, el botón debe ocultarse cuando escribe "sí" en el cuadro de entrada).
La alternativa sería NO utilizar un alcance aislado , que en realidad es lo que realmente quiero aquí, ya que no es necesario que el alcance de esta directiva esté aislado. El único problema que tengo es, ¿cómo llamo a un método en el alcance principal si no lo paso en un alcance aislado ?
Aquí hay un jsfiddle en el que NO estoy usando un alcance aislado y el ng-hide funciona bien, pero, por supuesto, la llamada a confirmAction () no funciona y no sé cómo hacer que funcione.
Tenga en cuenta que la respuesta que realmente estoy buscando es cómo llamar a funciones en el alcance externo SIN usar un alcance aislado. Y no estoy interesado en hacer que este diálogo de confirmación funcione de otra manera, porque el objetivo de esta pregunta es averiguar cómo realizar llamadas al alcance externo y aún poder hacer que otras directivas funcionen en contra del alcance principal.
Alternativamente, me interesaría conocer soluciones que utilicen un alcance aislado si otras directivas aún funcionan en contra del alcance principal , pero no creo que esto sea posible.
fuente
Respuestas:
Dado que la directiva solo llama a una función (y no intenta establecer un valor en una propiedad), puede usar $ eval en lugar de $ parse (con un alcance no aislado):
O mejor, simplemente use $ apply , que $ eval () evaluará su argumento contra el alcance:
Violín
fuente
confirm-action="doIt(arg1)"
, y luego establecerlosscope.arg1
antes de llamar a $ eval. Sin embargo, probablemente sería más limpio usar $ parse: stackoverflow.com/a/16200618/215945scope.$eval(attrs.confirmAction({arg1: 'blah'})
no funcionará. Necesitaría usar $ parse con esa sintaxis.Desea hacer uso del servicio $ parse en AngularJS.
Entonces, para tu ejemplo:
Hay un problema con configurar una propiedad usando $ parse, pero te dejaré cruzar ese puente cuando llegues a él.
fuente
scope:true
) funciona porque la directiva no creará un nuevo alcance en absoluto y, por lo tanto, lascope
propiedad a la que hace referencia en lalink
función es exactamente el mismo alcance que el alcance 'principal' anteriormente.Llame explícitamente
hideButton
al ámbito principal.Aquí está el violín: http://jsfiddle.net/pXej2/5/
Y aquí está el HTML actualizado:
fuente
Primero, un pequeño punto: en este caso, el alcance del controlador externo no es el alcance principal del alcance de la directiva; el alcance del controlador exterior es alcance de la directiva. En otras palabras, los nombres de variables usados en la directiva se buscarán directamente en el alcance del controlador.
A continuación, la escritura
attrs.confirmAction()
no funciona porqueattrs.confirmAction
para este botón,es la cadena
"doIt()"
, y no puede llamar a una cadena, por ejemplo"doIt()"()
.Tu pregunta realmente es:
En JavaScript, la mayoría de las funciones se llaman mediante notación de puntos, como esta:
Pero también puede usar la notación de matriz:
Tenga en cuenta que el valor del índice es una cadena . Entonces, en su directiva, simplemente puede hacer esto:
fuente