it-swarm.com.de

AngularJS. Aufrufen der Controller-Funktion von außerhalb der Controller-Komponente

Wie kann ich eine unter dem Controller definierte Funktion von einer beliebigen Stelle der Webseite (außerhalb der Controller-Komponente) aufrufen?

Es funktioniert einwandfrei, wenn ich den "get" -Button drücke. Aber ich muss es von außerhalb von Div Controller aufrufen. Die Logik ist: Standardmäßig ist mein div ausgeblendet. Irgendwo im Navigationsmenü drücke ich eine Taste und sie sollte () meine div anzeigen und die Funktion "get" ausführen. Wie kann ich das erreichen?

Meine Webseite ist:

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

Mein 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){ }
      });
    };
   }
186
Pavel Zdarov

Hier ist eine Möglichkeit, die Funktion des Controllers von außerhalb aufzurufen:

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

dabei ist get() eine Funktion Ihres Controllers.

Sie können wechseln

document.getElementById('yourControllerElementID')` 

zu

$('#yourControllerElementID')

Wenn Sie jQuery verwenden.

Wenn Ihre Funktion eine Änderung in Ihrer Ansicht bedeutet, sollten Sie auch anrufen

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

um die Änderungen zu übernehmen.

Außerdem sollten Sie beachten, dass Bereiche nach dem Laden der Seite initialisiert werden. Daher sollten Methoden von außerhalb des Bereichs immer nach dem Laden der Seite aufgerufen werden. Sonst kommen Sie überhaupt nicht zum Ziel.

PDATE:

Mit den neuesten Versionen von Angular sollten Sie verwenden

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

Und ja, das ist in der Tat eine schlechte Übung, aber manchmal müssen Dinge einfach schnell und schmutzig erledigt werden.

322
Dmitry Mina

Ich habe ein Beispiel im Internet gefunden.

Ein Typ hat diesen Code geschrieben und perfekt funktioniert

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

* Ich habe einige Änderungen vorgenommen, siehe Original: font JSfiddle

37
Roger Ramos

Die Antwort von Dmitry funktioniert gut. Ich habe nur ein einfaches Beispiel mit der gleichen Technik gemacht.

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 ; 
    }
}
11
Razan Paul

Die Lösung angular.element(document.getElementById('ID')).scope().get() hat in angular 1.5.2 aufgehört, für mich zu arbeiten. In einem Kommentar wurde erwähnt, dass dies auch in 1.4.9 nicht funktioniert. Ich habe es behoben, indem ich den Gültigkeitsbereich in einer globalen Variablen gespeichert habe:

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

aufruf von benutzerdefiniertem Code:

scopeHolder.bar()

wenn Sie den Bereich nur auf diese Methode beschränken möchten. Minimierung der Exposition des gesamten Bereichs. Verwenden Sie die folgende Technik.

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

aufruf von benutzerdefiniertem Code:

scopeHolder()
10
user1121883

Ich würde die Factory lieber als Abhängigkeiten von den Controllern einbinden, als ihnen eine eigene Codezeile zuzuweisen: 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'];

7
getsetbro

Es kann erwägenswert sein, Ihr Menü ohne zugehörigen Bereich zu haben. Es ist nicht wirklich der angular Weg.

Wenn Sie dies jedoch tun müssen, können Sie dies tun, indem Sie die Funktionen zu $ ​​rootScope hinzufügen und dann innerhalb dieser Funktionen $ broadcast verwenden, um Ereignisse zu senden. Ihr Controller verwendet dann $ on, um auf diese Ereignisse zu warten.

Eine andere zu berücksichtigende Sache, wenn Sie Ihr Menü ohne Gültigkeitsbereich haben, ist, dass, wenn Sie mehrere Routen haben, alle Ihre Steuerungen ihre eigene Aktualisierung haben müssen und Funktionen erhalten müssen. (Dies setzt voraus, dass Sie mehrere Controller haben)

5
Anton

Ich arbeite mit $ http. Wenn ich Informationen aus einer Ressource abrufen möchte, gehe ich folgendermaßen vor:

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

Und der Code im Controller:

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

Ich sende dem Dienst, welche Funktion in der Steuerung aufzurufen ist

4
rodrimmb

Ich habe mehrere Routen und mehrere Controller, daher konnte ich die akzeptierte Antwort nicht zum Laufen bringen. Ich fand, dass das Hinzufügen der Funktion zum Fenster funktioniert:

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;

}

Dies kann dann außerhalb des Controllers erfolgen:

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

Ich bin ein Ionic Framework-Benutzer und derjenige, den ich gefunden habe, um den $ -Bereich des aktuellen Controllers konsistent bereitzustellen, ist:

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

Ich vermute, dass dies für die meisten Szenarien unabhängig vom Framework (oder nicht) geändert werden kann, indem die Abfrage gefunden wird, die auf bestimmte DOM-Elemente abzielt, die nur während einer bestimmten Controller-Instanz verfügbar sind.

0
Matt Ray