otro - AngularJS. Cómo llamar a la función del controlador desde fuera del componente del controlador
llamar funcion angular desde html (9)
¿Cómo puedo llamar a la función definida bajo el controlador desde cualquier lugar de la página web (fuera del componente del controlador)?
Funciona perfectamente cuando presiono el botón "get". Pero necesito llamarlo desde fuera del controlador div. La lógica es: por defecto mi div está oculto. En algún lugar del menú de navegación, presiono un botón y debería mostrar () mi div y ejecutar la función "get". ¿Cómo puedo lograr esto?
Mi página web es:
<div ng-controller="MyController">
<input type="text" ng-model="data.firstname" required>
<input type=''text'' ng-model="data.lastname" required>
<form ng-submit="update()"><input type="submit" value="update"></form>
<form ng-submit="get()"><input type="submit" value="get"></form>
</div>
Mi 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){ }
});
};
}
Aquí hay una manera de llamar a la función del controlador desde afuera:
angular.element(document.getElementById(''yourControllerElementID'')).scope().get();
donde get()
es una función de su controlador.
Puedes cambiar
document.getElementById(''yourControllerElementID'')`
a
$(''#yourControllerElementID'')
Si está usando jQuery.
Además, si su función significa cambiar algo en su Vista, debe llamar
angular.element(document.getElementById(''yourControllerElementID'')).scope().$apply();
para aplicar los cambios
Una cosa más, debe tener en cuenta es que los ámbitos se inicializan después de que se carga la página, por lo que los métodos de llamada desde fuera del alcance siempre se deben hacer después de que se cargue la página. De lo contrario, no llegarás al alcance en absoluto.
ACTUALIZAR:
Con las últimas versiones de angular, debes usar
angular.element(document.getElementById(''yourControllerElementID'')).injector().get(''$rootScope'')
Y sí, esto es, de hecho, una mala práctica , pero a veces solo necesitas cosas rápidas y sucias.
Encontré un ejemplo en internet.
Un tipo escribió este código y trabajó perfectamente
HTML
<div ng-cloak ng-app="ManagerApp">
<div id="MainWrap" class="container" ng-controller="ManagerCtrl">
<span class="label label-info label-ext">Exposing Controller Function outside the module via onClick function call</span>
<button onClick=''ajaxResultPost("Update:Name:With:JOHN","accept",true);''>click me</button>
<br/> <span class="label label-warning label-ext" ng-bind="customParams.data"></span>
<br/> <span class="label label-warning label-ext" ng-bind="customParams.type"></span>
<br/> <span class="label label-warning label-ext" ng-bind="customParams.res"></span>
<br/>
<input type="text" ng-model="sampletext" size="60">
<br/>
</div>
</div>
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);
});
}
* Hice algunas modificaciones, ver original: font JSfiddle
La respuesta de Dmitry funciona bien. Acabo de hacer un ejemplo simple usando la misma técnica.
jsfiddle: http://jsfiddle.net/o895a8n8/5/
<button onclick="call()">Call Controller''s method from outside</button>
<div id="container" ng-app="" ng-controller="testController">
</div>
.
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 ;
}
}
La solución angular.element(document.getElementById(''ID'')).scope().get()
dejó de funcionar para mí en angular 1.5.2. Mención aparte en un comentario de que esto tampoco funciona en 1.4.9. Lo arreglé guardando el alcance en una variable global:
var scopeHolder;
angular.module(''fooApp'').controller(''appCtrl'', function ($scope) {
$scope = function bar(){
console.log("foo");
};
scopeHolder = $scope;
})
llamar desde un código personalizado:
scopeHolder.bar()
si quiere restringir el alcance a solo este método. Para minimizar la exposición de todo el alcance. usa la siguiente técnica.
var scopeHolder;
angular.module(''fooApp'').controller(''appCtrl'', function ($scope) {
$scope.bar = function(){
console.log("foo");
};
scopeHolder = $scope.bar;
})
llamar desde un código personalizado:
scopeHolder()
Prefiero incluir la fábrica como dependencias en los controladores que inyectarlos con su propia línea de código: 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''];
Puede valer la pena considerar si tener el menú sin un alcance asociado es el camino correcto. No es realmente el camino angular.
Pero, si es la forma en que necesita ir, puede hacerlo agregando las funciones a $ rootScope y luego dentro de esas funciones usando $ broadcast para enviar eventos. su controlador usa $ on para escuchar esos eventos.
Otra cosa a considerar si termina teniendo su menú sin un alcance es que si tiene múltiples rutas, entonces todos sus controladores tendrán que tener sus propias funciones upate y get. (esto es asumiendo que tienes múltiples controladores)
Soy un usuario de framework Ionic y el que encontré que proporcionaría consistentemente el $ scope del controlador actual es:
angular.element(document.querySelector(''ion-view[nav-view="active"]'')).scope()
Sospecho que esto se puede modificar para adaptarse a la mayoría de los escenarios independientemente del marco (o no) al encontrar la consulta que se dirigirá a los elementos DOM específicos que están disponibles solo durante una instancia de controlador determinada.
Tengo múltiples rutas y múltiples controladores, así que no pude lograr que la respuesta aceptada funcionara. Encontré que agregar la función a la ventana funciona:
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;
}
Luego, fuera del controlador, esto se puede hacer:
function ElsewhereOnThePage() {
if (typeof(fooreinit) == ''function'') { fooreinit(); }
}
Utilizo para trabajar con $ http, cuando quiero obtener información de un recurso, hago lo siguiente:
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);
}}
});
Y el código en el controlador:
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);
}
}
Le envío al servicio qué función tiene que llamar en el controlador