AngularJS. Comment appeler la fonction contrôleur depuis l’extérieur du composant contrôleur

Comment puis-je appeler la fonction définie sous le contrôleur depuis n’importe quel endroit de la page Web (en dehors du composant du contrôleur)?

Cela fonctionne parfaitement quand j’appuie sur le bouton “get”. Mais je dois l’appeler de l’extérieur du contrôleur div. La logique est la suivante: par défaut, mon div est caché. Quelque part dans le menu de navigation j’appuie sur un bouton et il devrait afficher () mon div et exécuter la fonction “get”. Comment je peux y arriver?

Ma page Web est:

Mes js:

  function MyController($scope) { // default data and structure $scope.data = { "firstname" : "Nicolas", "lastname" : "Cage" }; $scope.get = function() { $.ajax({ url: "/php/get_data.php?", type: "POST", timeout: 10000, // 10 seconds for getting result, otherwise error. error:function() { alert("Temporary error. Please try again...");}, complete: function(){ $.unblockUI();}, beforeSend: function(){ $.blockUI()}, success: function(data){ json_answer = eval('(' + data + ')'); if (json_answer){ $scope.$apply(function () { $scope.data = json_answer; }); } } }); }; $scope.update = function() { $.ajax({ url: "/php/update_data.php?", type: "POST", data: $scope.data, timeout: 10000, // 10 seconds for getting result, otherwise error. error:function() { alert("Temporary error. Please try again...");}, complete: function(){ $.unblockUI();}, beforeSend: function(){ $.blockUI()}, success: function(data){ } }); }; } 

Voici un moyen d’appeler la fonction du contrôleur depuis l’extérieur:

 angular.element(document.getElementById('yourControllerElementID')).scope().get(); 

get() est une fonction de votre contrôleur.

Vous pouvez changer

 document.getElementById('yourControllerElementID')` 

à

 $('#yourControllerElementID') 

Si vous utilisez jQuery.

En outre, si votre fonction signifie changer quelque chose sur votre vue, vous devez appeler

 angular.element(document.getElementById('yourControllerElementID')).scope().$apply(); 

appliquer les modifications.

Encore une chose, vous devez noter que les étendues sont initialisées après le chargement de la page, donc les méthodes d’appel en dehors de la scope doivent toujours être effectuées après le chargement de la page. Sinon, vous n’arriverez pas à la scope du tout.

METTRE À JOUR:

Avec les dernières versions de angular, vous devriez utiliser

 angular.element(document.getElementById('yourControllerElementID')).injector().‌​get('$rootScope') 

Et oui, en fait, c’est une mauvaise pratique , mais parfois vous avez juste besoin de faire les choses rapidement et sale.

J’ai trouvé un exemple sur internet.

Un gars a écrit ce code et a parfaitement fonctionné

HTML

 
Exposing Controller Function outside the module via onClick function call




JAVASCRIPT

 var angularApp = angular.module('ManagerApp', []); angularApp.controller('ManagerCtrl', ['$scope', function ($scope) { $scope.customParams = {}; $scope.updateCustomRequest = function (data, type, res) { $scope.customParams.data = data; $scope.customParams.type = type; $scope.customParams.res = res; $scope.sampletext = "input text: " + data; }; }]); function ajaxResultPost(data, type, res) { var scope = angular.element(document.getElementById("MainWrap")).scope(); scope.$apply(function () { scope.updateCustomRequest(data, type, res); }); } 

Démo

* J’ai fait quelques modifications, voir l’original: font JSfiddle

La réponse de Dmitry fonctionne bien. Je viens de faire un exemple simple en utilisant la même technique.

jsfiddle: http://jsfiddle.net/o895a8n8/5/

  

.

 function call() { var scope = angular.element(document.getElementById('container')).scope(); scope.$apply(function(){ scope.msg = scope.msg + ' I am the newly addded message from the outside of the controller.'; }) alert(scope.returnHello()); } function testController($scope) { $scope.msg = "Hello from a controller method."; $scope.returnHello = function() { return $scope.msg ; } } 

Je préférerais inclure l’usine comme dépendances sur les contrôleurs plutôt que de leur injecter leur propre ligne de code: http://jsfiddle.net/XqDxG/550/

 myModule.factory('mySharedService', function($rootScope) { return sharedService = {thing:"value"}; }); function ControllerZero($scope, mySharedService) { $scope.thing = mySharedService.thing; 

ControllerZero. $ Inject = [‘$ scope’, ‘mySharedService’];

La solution angular.element(document.getElementById('ID')).scope().get() cessé de fonctionner pour moi en angular 1.5.2. Sombody mentionne dans un commentaire que cela ne fonctionne pas aussi dans 1.4.9. Je l’ai corrigé en stockant la scope dans une variable globale:

 var scopeHolder; angular.module('fooApp').controller('appCtrl', function ($scope) { $scope = function bar(){ console.log("foo"); }; scopeHolder = $scope; }) 

appel du code personnalisé:

 scopeHolder.bar() 

si vous souhaitez restreindre la scope à cette méthode uniquement. Pour minimiser l’exposition de toute la scope. utiliser la technique suivante.

 var scopeHolder; angular.module('fooApp').controller('appCtrl', function ($scope) { $scope.bar = function(){ console.log("foo"); }; scopeHolder = $scope.bar; }) 

appel du code personnalisé:

 scopeHolder() 

Il peut être utile de se demander si le fait d’avoir votre menu sans scope associée est la bonne façon de procéder. Ce n’est pas vraiment la voie angular.

Mais si c’est le chemin à parcourir, vous pouvez le faire en ajoutant les fonctions à $ rootScope, puis dans ces fonctions en utilisant $ broadcast pour envoyer des événements. Votre contrôleur utilise ensuite $ on pour écouter ces événements.

Une autre chose à considérer si vous finissez par avoir votre menu sans étendue est que si vous avez plusieurs routes, tous vos contrôleurs devront avoir leurs propres fonctions et obtenir des fonctions. (ceci suppose que vous avez plusieurs contrôleurs)

J’utilise pour travailler avec $ http, quand je veux obtenir des informations d’une ressource, je fais ce qui suit:

 angular.module('services.value', []) .service('Value', function($http, $q) { var URL = "http://localhost:8080/myWeb/rest/"; var valid = false; return { isValid: valid, getIsValid: function(callback){ return $http.get(URL + email+'/'+password, {cache: false}) .success(function(data){ if(data === 'true'){ valid = true; } }).then(callback); }} }); 

Et le code dans le contrôleur:

 angular.module('controllers.value', ['services.value']) .controller('ValueController', function($scope, Value) { $scope.obtainValue = function(){ Value.getIsValid(function(){$scope.printValue();}); } $scope.printValue = function(){ console.log("Do it, and value is " Value.isValid); } } 

J’envoie au service quelle fonction doit appeler dans le contrôleur

J’ai plusieurs routes et plusieurs contrôleurs, donc je ne pouvais pas obtenir la réponse acceptée. J’ai trouvé que l’ajout de la fonction à la fenêtre fonctionne:

 fooModule.controller("fooViewModel", function ($scope, fooService, $http, $q, $routeParams, $window, $location, viewModelHelper, $interval) { $scope.initFoo = function () { // do angular stuff } var initialize = function () { $scope.initFoo(); } initialize(); window.fooreinit = initialize; } 

Ensuite, en dehors du contrôleur, cela peut être fait:

 function ElsewhereOnThePage() { if (typeof(fooreinit) == 'function') { fooreinit(); } } 

Je suis un utilisateur de structure ionique et celui que j’ai trouvé qui fournirait systématiquement la scope $ du contrôleur actuel est:

angular.element(document.querySelector('ion-view[nav-view="active"]')).scope()

Je pense que cela peut être modifié pour s’adapter à la plupart des scénarios, quel que soit le framework (ou non), en recherchant la requête qui ciblera les éléments DOM spécifiques disponibles uniquement lors d’une instance de contrôleur donnée.