Kann ich in jedem Controller eine Funktion in Winkel zur Verfügung stellen?

191

Wenn ich eine Dienstprogrammfunktion habe foo, die ich von überall in meiner ng-appDeklaration aufrufen möchte . Gibt es eine Möglichkeit, wie ich es in meinem Modul-Setup global zugänglich machen kann, oder muss ich es dem Bereich in jedem Controller hinzufügen?

Ludwig Magnusson
quelle
Ich bin mir nicht 100% sicher, aber es besteht die Möglichkeit, dass Sie es auch so auf Ihrem Modul definieren können: module.value('myFunc', function(a){return a;});und es dann namentlich in Ihre Controller einfügen. (Wenn man einen Dienst vermeiden möchte)
user2173353
Das bedeutet, dass ich es manuell zu jedem Controller hinzufügen muss. $ rootScope ist der richtige Weg für das, was ich vor fast 2 Jahren machen wollte =)
Ludwig Magnusson
OK. :) Ich benutze nur häufiger Direktiven mit isoliertem Gültigkeitsbereich als normale Controller und muss sowieso alles injizieren. Ich mag den modularen Codestil, den dies bietet. Außerdem müssen Sie sich in keiner Weise mit übergeordneten Bereichen herumschlagen und müssen nicht viel danach suchen, woher Ihre Bereichsvariablen stammen. :)
user2173353

Antworten:

290

Grundsätzlich haben Sie zwei Möglichkeiten: Definieren Sie es entweder als Service oder platzieren Sie es in Ihrem Stammbereich. Ich würde vorschlagen, dass Sie einen Dienst daraus machen, um eine Verschmutzung des Stammbereichs zu vermeiden. Sie erstellen einen Dienst und stellen ihn wie folgt in Ihrem Controller zur Verfügung:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.factory('myService', function() {
        return {
            foo: function() {
                alert("I'm foo!");
            }
        };
    });

    myApp.controller('MainCtrl', ['$scope', 'myService', function($scope, myService) {
        $scope.callFoo = function() {
            myService.foo();
        }
    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="callFoo()">Call foo</button>
</body>
</html>

Wenn dies für Sie keine Option ist, können Sie es wie folgt zum Stammbereich hinzufügen:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.run(function($rootScope) {
        $rootScope.globalFoo = function() {
            alert("I'm global foo!");
        };
    });

    myApp.controller('MainCtrl', ['$scope', function($scope){

    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="globalFoo()">Call global foo</button>
</body>
</html>

Auf diese Weise können alle Ihre Vorlagen aufrufen, globalFoo()ohne sie vom Controller an die Vorlage übergeben zu müssen.

Anders Ekdahl
quelle
5
Was ist in der ersten Lösung, wenn es Tonnen von foo()Funktionen gibt? $scope.callFoo()Es ist zu viel Arbeit, für jeden von ihnen einen Wrapper zu erstellen. Wie kann ich alle Funktionen einer Bibliothek in den Bereich "einfügen" , damit sie in der Vorlage verwendet werden kann? Ich habe eine große Einheitenumrechnungsbibliothek, die in meiner Vorlage verfügbar sein soll.
AlexStack
3
Meine Frage auch. Ich habe es ausprobiert und es funktioniert: Sie können es "anhängen", indem Sie sagen, $scope.callFoo = myService.foo;dass an jeder Stelle, an der Sie es verwenden möchten, ein neuer Wrapper erstellt wird.
Fitter Man
1
Vielen Dank für Ihre Hilfe. Ich habe mich gefragt, wie ich eine Funktion zum Ändern der Sprache in meiner App verfügbar machen kann, und $ rootScope hat den Job erledigt. Ich wollte das Übersetzungsmodul von der Anwendung fernhalten, damit ich es auch in andere Apps einbinden kann.
Paulo Pedroso
Ich würde vorschlagen, für diesen speziellen Fall einen Winkelwert anstelle einer Factory zu verwenden, es sei denn, Sie planen, mehrere Funktionen innerhalb eines Dienstes zu haben. Wenn es sich nur um eine Funktion handelt, machen Sie sie zu einem Wert.
Nicholas Blasgen
Ich habe Fehler: [$ Injektor: unpr]
Mark Thien
53

Sie können sie auch kombinieren, denke ich:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
</body>
</html>
Ric
quelle
7
Ich denke, dies sollte die richtige Antwort sein, gerechtfertigt durch die Antwort von @Praym. Es ist nicht sinnvoll, eine Dienstabhängigkeit in 10 verschiedenen Controllern anzugeben.
Jvannistelrooy
Kann der Dienst Methoden / Funktionen enthalten, die CRUD-Eigenschaften / -Variablen in die $rootScope?
Jezmck
44

Obwohl der erste Ansatz als "eckiger" Ansatz empfohlen wird, ist dies meines Erachtens ein zusätzlicher Aufwand.

Überlegen Sie, ob ich diese myservice.foo-Funktion in 10 verschiedenen Controllern verwenden möchte. Ich muss diese 'myService'-Abhängigkeit und dann die $ scope.callFoo-Scope-Eigenschaft in allen zehn angeben. Dies ist einfach eine Wiederholung und verstößt irgendwie gegen das DRY-Prinzip.

Wenn ich den $ rootScope-Ansatz verwende, gebe ich diese globale Funktion gobalFoo nur einmal an und sie wird in allen meinen zukünftigen Controllern verfügbar sein, egal wie viele.

Praym
quelle
5
Es kann einen gewissen Wert in der 'Dokumentation' der Controller geben, wo sie diesen globalen Serviceabruf erhalten. Wenn Sie einen Ihrer Controller in eine andere Anwendung ziehen würden, wäre weniger klar, woher diese globale Funktion stammt. Ich höre jedoch Ihre Argumentation erkennen.
Matthew Payne
Es muss nur in den Bereich aufgenommen werden, wenn Sie es aus der Ansicht aufrufen müssen. In der Steuerung können Sie es direkt vom Dienst aus aufrufen.
mcv
10
Dies ist ein Kommentar, keine Antwort
Elliott
Die Variable $ rootScope ist bei der Seitenaktualisierung immer null. In diesem Fall erhalten Sie die Funktion nicht. Aus diesem Grund ist es gut, den Dienst einzuschleusen und seine Referenz in der Anwendung zu verwenden.
Ehsan Hafeez
4

AngularJs hat " Services " und " Factories " nur für Probleme wie Ihre. Diese werden verwendet, um etwas Globales zwischen Controllern, Direktiven, anderen Services oder anderen AngularJs-Komponenten zu haben. Sie können Funktionen definieren, Daten speichern, Funktionen berechnen oder was auch immer Sie wollen in Services und verwenden Sie sie in AngularJs Components als Global .like

angular.module('MyModule', [...])
  .service('MyService', ['$http', function($http){
    return {
       users: [...],
       getUserFriends: function(userId){
          return $http({
            method: 'GET',
            url: '/api/user/friends/' + userId
          });
       }
       ....
    }
  }])

wenn du mehr brauchst

Erfahren Sie mehr darüber, warum wir AngularJs Services und Fabriken benötigen

Hazarapet Tunanyan
quelle
0

Ich bin etwas neuer in Angular, aber ich fand es nützlich (und ziemlich einfach), ein globales Skript zu erstellen, das ich vor dem lokalen Skript auf meine Seite lade, mit globalen Variablen, auf die ich sowieso auf allen Seiten zugreifen muss. In diesem Skript habe ich ein Objekt namens "globalFunctions" erstellt und die Funktionen hinzugefügt, auf die ich global als Eigenschaften zugreifen muss. zB globalFunctions.foo = myFunc();. Dann habe ich in jedem lokalen Skript geschrieben $scope.globalFunctions = globalFunctions;und habe sofort Zugriff auf alle Funktionen, die ich dem globalFunctions-Objekt im globalen Skript hinzugefügt habe.

Dies ist eine kleine Problemumgehung und ich bin mir nicht sicher, ob es Ihnen hilft, aber es hat mir definitiv geholfen, da ich viele Funktionen hatte und es ein Schmerz war, alle auf jeder Seite hinzuzufügen.

Izzy
quelle
1
Ich bin nur neugierig, warum die Abstimmungen? Ich bin neu und würde gerne von den Profis wissen.
Izzy
Scheint mir eine funktionierende Lösung zu sein. Das einzige, was ich befürworten würde, um sicherzustellen, dass Ihr Bereich ausreichend isoliert ist, ist, eine globale Root-Javascript-Dienstprogrammklasse zu erstellen und Ihre Dienstprogrammmethoden daran zu hängen, damit Sie nicht versehentlich auf einen anderen Funktionsnamen in der riesiges Meer von Dingen, die Angular injiziert hat.
JE Carter II
Eine Sache zu beachten, und vielleicht, warum dies herabgestuft wird, könnten Sie nur diese Funktionen in Ihren Vorlagen verwenden, nicht Ihre .ts-Module, da Ihre Funktionsaufrufe beim Kompilieren nicht aufgelöst würden. Dies ist der Grund dafür, es "eckig" zu machen. Wenn Sie Ihren Vorlagen jedoch nur Dekorateure und dergleichen hinzufügen möchten, ist eine globale Dienstprogrammdatei einfach und in Ordnung.
JE Carter II