Подтвердить что ты не робот

AngularJS. Как вызвать функцию контроллера извне компонента контроллера

Как я могу вызывать функцию, определенную под контроллером, из любого места веб-страницы (вне компонента контроллера)?

Он отлично работает, когда я нажимаю кнопку "получить". Но мне нужно вызвать его из-за пределов контроллера div. Логика такова: по умолчанию мой div скрыт. Где-то в меню навигации я нажимаю кнопку, и она должна показывать() мой div и выполнять функцию "получить". Как я могу это достичь?

Моя веб-страница:

<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>

Мои 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){ }
      });
    };
   }
4b9b3361

Ответ 1

Вот способ вызова функции контроллера извне:

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

где get() - это функция от вашего контроллера.

Вы можете переключать

document.getElementById('yourControllerElementID')` 

to

$('#yourControllerElementID')

Если вы используете jQuery.

Кроме того, если ваша функция означает изменение чего-либо на вашем представлении, вы должны позвонить

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

чтобы применить изменения.

Еще одна вещь, вы должны отметить, что области будут инициализированы после загрузки страницы, поэтому вызов методов из-за пределов видимости всегда должен выполняться после загрузки страницы. Иначе вы вообще не попадете в сферу действия.

UPDATE:

С последними версиями angular вы должны использовать

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

И да, это, по сути, плохая практика, но иногда вам просто нужно делать вещи быстро и грязно.

Ответ 2

Я нашел пример в интернете.

Какой-то парень написал этот код и отлично работал

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);
    });
}

Demo

* Я сделал некоторые изменения, см. оригинал: шрифт JSfiddle

Ответ 3

Дмитрий отвечает отлично. Я просто сделал простой пример, используя ту же технику.

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

<button onclick="call()">Call Controller 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 ; 
    }
}

Ответ 4

Решение angular.element(document.getElementById('ID')).scope().get() перестала работать для меня в angular 1.5.2. Sombody упоминает в комментарии, что это тоже не работает в 1.4.9. Я исправил его, сохранив область в глобальной переменной:

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

вызов из пользовательского кода:

scopeHolder.bar()

если вы хотите ограничить область только этим методом. Чтобы свести к минимуму воздействие всего объема. использование следующий technique.

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

вызов из пользовательского кода:

scopeHolder()

Ответ 5

Я предпочел бы включить factory в качестве зависимостей от контроллеров, чем вставлять их своей собственной строкой кода: http://jsfiddle.net/XqDxG/550/

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

function ControllerZero($scope, mySharedService) {
    $scope.thing = mySharedService.thing;

ControllerZero. $injection = ['$ scope', 'mySharedService'];

Ответ 6

Возможно, стоит подумать о том, правильно ли вы хотите иметь свое меню без какой-либо связанной с ним области. Это не действительно способ angular.

Но если это так, как вам нужно, вы можете сделать это, добавив функции в $rootScope, а затем в те функции, используя $broadcast для отправки событий. ваш контроллер затем использует $on для прослушивания этих событий.

Еще одна вещь, которую следует учитывать, если вы в конечном итоге имеете свое меню без области видимости, состоит в том, что если у вас есть несколько маршрутов, все ваши контроллеры должны будут иметь свои собственные функции и получить функции. (предполагается, что у вас несколько контроллеров)

Ответ 7

Я использую для работы с $http, когда хочу получить некоторую информацию из ресурса, я делаю следующее:

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);
    }}
    });

И код в контроллере:

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);
    }
}

Я посылаю службе, какая функция должна вызывать в контроллере

Ответ 8

У меня есть несколько маршрутов и несколько контроллеров, поэтому я не мог получить принятый ответ на работу. Я обнаружил, что добавление функции в окно работает:

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;

}

Затем вне контроллера это можно сделать:

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

Ответ 9

Вызовите функцию Angular Scope снаружи контроллера.

// Simply Use "Body" tag, Don't try/confuse using id/class.

var scope = angular.element('body').scope();             
scope.$apply(function () {scope.YourAngularJSFunction()});      

Ответ 10

Я являюсь пользователем Ionic framework, и тот, который я нашел, который будет последовательно предоставлять текущую переменную $scope:

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

Я подозреваю, что это может быть изменено, чтобы соответствовать большинству сценариев, независимо от структуры (или нет), путем поиска запроса, который будет нацелен на определенные элементы DOM, доступные только в течение данного экземпляра контроллера.