switch angularjs angularjs-directive angularjs-ng-click

angularjs - switch - ¿Cómo invocar ng-click desde una directiva parcial?



ng-if (2)

Tengo una directiva que tiene un ámbito local donde un parcial contiene ng-clic.

El violín está allí: http://jsfiddle.net/stephanedeluca/QRZFs/13/

Desafortunadamente, como moví mi código a la directiva, ng-click ya no dispara.

El controlador y la directiva son los siguientes:

var app = angular.module(''myApp'', [''ngSanitize'']); app.directive(''plantStages'', function ($compile) { return { restrict: ''E'', transclude: true, template: ''<figure class="cornStages">/ <p ng-transclude style="color: skyblue"></p>/ <hr/>/ <p ng-bind-html="title"></p>/ <p ng-bind-html="subtitle">{{subtitle}}</p>/ <ul>/ <li ng-repeat="stage in stages" ng-click="changePage(stage)">{{stage}}</li>/ </ul>/ </figure>'', scope: { stages:"=", title:''@'' }, link: function (scope, element, attrs, ctrl, transclude) { if (!attrs.title) scope.title = "Default title"; } }; }); app.controller(''myCtrl'', function ($scope, $location, $http) { $scope.stages = [''floraison'', ''montaison'']; $scope.changePage = function (page) { var url = "corn.page.html#/"+page; console.log("Change page "+page+" with url "+url); alert("about to change page as follows: document.location.href = "+url); }; });

El html que lo invoca es el siguiente:

<div ng-controller="myCtrl"> Stages, <p ng-repeat="stage in stages">{{stage}}</p> <hr/> Plant stages <plant-stages title="<b>Exploration<br/>du cycle</b>" subtitle="<em>This is a<br/>sub title</em>" stages="stages" > Inner<br/>directive </plant-stages> </div>

¿Alguna idea?


La idea de las directivas es tratarlas como componentes reutilizables y evitar dependencias externas siempre que sea posible. Si tiene la posibilidad de definir el comportamiento de su directiva en su propio controlador, hágalo.

module.directive(''myDirective'', function () { return { restrict: ''E'', controller: function() { /* behaviour here */ }, template: ''<div>Directive Template</div>'', scope: { /* directive scope */ } }; });

Si esto no es posible, puede pasar la función como se explica en la pregunta vinculada (ver el comentario anterior). Compruebe el violín actualizado .


No se puede acceder a changePage() definido en el ámbito del controlador directamente desde la directiva, ya que su directiva tiene un alcance aislado. Sin embargo, todavía hay varias formas de hacerlo:

Opción 1:

La opción 1 es la opción más simple. Sin embargo, es muy parecido a una solución alternativa y no recomiendo usarla ampliamente. Puede obtener el alcance de su controlador del elemento pasado a la función de enlace e invocar changePage allí:

link: function (scope, element, attrs, ctrl, transclude) { if (!attrs.title) scope.title = "Default title"; scope.changePage = element.scope().changePage; // <= Get parent scope from element, it will have changePage() }

Opcion 2:

Si no tiene ninguna lógica que implique alcance definido en el controlador externo (como en su ejemplo), puede definir el controlador interno para su directiva y realizarlo allí:

app.directive(''plantStages'', function ($compile) { return { ... controller: [''$scope'', function($scope) { $scope.changePage = function(page) { var url = "corn.page.html#/"+page; console.log("Change page "+page+" with url "+url); alert("about to change page as follows: document.location.href = "+url); } }] }; });

Opción 3:

Si desea reutilizar la lógica definida en changePage() en diferentes directivas y controladores, la mejor manera de hacerlo es mover la lógica a algún servicio que pueda ser inyectado tanto al controlador como a la directiva:

app.service(''changePageService'', function() { this.changePage = function(page) { var url = "corn.page.html#/"+page; console.log("Change page "+page+" with url "+url); alert("about to change page as follows: document.location.href = "+url); } }); app.controller(''myCtrl'', function ($scope, $location, $http, changePageService) { ... changePageService.changePage(''page''); ... }); app.directive(''plantStages'', function ($compile) { ... controller: [''$scope'', ''changePageService'', function($scope, changePageService) { $scope.changePage = changePageService.changePage; }] ... });

Opción 4:

Puede pasar un fragmento de código como changePage(page) como valor de algún atributo de la directiva y dentro de la directiva definir propiedad de alcance con ''&'' que creará una función que se ejecutará en el alcance del controlador externo con argumentos pasados ​​a esa función. Ejemplo:

JavaScript

app.directive(''plantStages'', function ($compile) { return { restrict: ''E'', transclude: true, template: ''<figure class="cornStages">/ <p ng-transclude style="color: skyblue"></p>/ <hr/>/ <p ng-bind-html="title"></p>/ <p ng-bind-html="subtitle"></p>/ <ul>/ <li ng-repeat="stage in stages" ng-click="changePage({page: stage})">{{stage}}</li>/ </ul>/ </figure>'', scope: { stages:"=", title:''@'', changePage:''&'' }, link: function (scope, element, attrs, ctrl, transclude) { if (!attrs.title) scope.title = "Default title"; } }; });

HTML

<div ng-controller="myCtrl"> Stages, <p ng-repeat="stage in stages">{{stage}}</p> <hr/> Plant stages <plant-stages title="<b>Exploration<br/>du cycle</b>" subtitle="<em>This is a<br/>sub title</em>" stages="stages" change-page="changePage(page)" > Inner<br/>directive </plant-stages>

Plunker: http://plnkr.co/edit/s4CFI3wxs0SOmZVhUkC4?p=preview