180 votes

Appeler AngularJS à partir d'un code existant

J'utilise AngularJS pour construire des contrôles HTML qui interagissent avec une application Flex existante. Tous les rappels de l'application Flex doivent être attachés à la fenêtre DOM.

Par exemple (dans AS3)

ExternalInterface.call("save", data);

Appeler

window.save = function(data){
    // want to update a service 
    // or dispatch an event here...
}

À partir de la fonction de redimensionnement JS, j'aimerais envoyer un événement qu'un contrôleur pourrait entendre. Il semble que la création d'un service soit la solution. Peut-on mettre à jour un service depuis l'extérieur d'AngularJS ? Un contrôleur peut-il écouter les événements d'un service ? Dans un expérience (cliquez pour le violon) Il semble que je puisse accéder à un service mais que la mise à jour des données du service ne soit pas répercutée dans la vue (dans l'exemple un <option> doit être ajouté à la <select> ).

Merci de votre attention !

293voto

Misko Hevery Points 25631

L'interopérabilité de l'extérieur d'Angular vers Angular est la même que le débogage d'une application Angular ou l'intégration d'une bibliothèque tierce.

Pour n'importe quel élément du DOM, vous pouvez faire cela :

  • angular.element(domElement).scope() pour obtenir la portée actuelle de l'élément
  • angular.element(domElement).injector() pour obtenir l'injecteur d'application actuel
  • angular.element(domElement).controller() pour obtenir l'aide de la ng-controller instance.

À partir de l'injecteur, vous pouvez accéder à n'importe quel service dans l'application angulaire. De même, à partir du scope, vous pouvez invoquer toutes les méthodes qui ont été publiées dans celui-ci.

Gardez à l'esprit que toute modification du modèle angulaire ou toute invocation de méthode sur le champ d'application doit être enveloppée dans le module $apply() comme ceci :

$scope.$apply(function(){
  // perform any model changes or method invocations here on angular app.
});

86voto

Peter Drinnan Points 1123

Misko a donné la bonne réponse (évidemment), mais certains d'entre nous, novices, peuvent avoir besoin d'une explication plus détaillée.

Lorsqu'il s'agit d'appeler du code AngularJS à partir d'applications patrimoniales, considérez le code AngularJS comme une "micro-application" existant dans un conteneur protégé au sein de votre application patrimoniale. Vous ne pouvez pas l'appeler directement (pour une très bonne raison), mais vous pouvez faire des appels à distance par le biais de l'objet $scope.

Pour utiliser l'objet $scope, vous devez obtenir le handle de $scope. Heureusement, c'est très facile à faire.

Vous pouvez utiliser l'id de n'importe quel élément HTML dans votre "micro-app" HTML AngularJS pour obtenir l'identifiant de l'application AngularJS $scope.

Par exemple, disons que nous voulons appeler quelques fonctions dans notre contrôleur AngularJS, comme sayHi() et sayBye(). Dans le HTML AngularJS (vue), nous avons une div avec l'id "MySuperAwesomeApp". Vous pouvez utiliser le code suivant, combiné avec jQuery pour obtenir la poignée de $scope :

var microappscope = angular.element($("#MySuperAwesomeApp")).scope();

Vous pouvez maintenant appeler les fonctions de votre code AngularJS par l'intermédiaire du scope handle :

// we are in legacy code land here...

microappscope.sayHi();

microappscope.sayBye();

Pour rendre les choses plus pratiques, vous pouvez utiliser une fonction pour saisir la poignée de l'oscilloscope à chaque fois que vous souhaitez y accéder :

function microappscope(){

    return angular.element($("#MySuperAwesomeApp")).scope();

}

Vos appels ressembleraient alors à ceci :

microappscope().sayHi();

microappscope().sayBye();

Vous pouvez voir un exemple de fonctionnement ici :

http://jsfiddle.net/peterdrinnan/2nPnB/16/

J'ai également montré ceci dans un diaporama pour le groupe AngularJS d'Ottawa (passez simplement aux deux dernières diapositives).

http://www.slideshare.net/peterdrinnan/angular-for-legacyapps

24voto

Wiseman Points 255

La meilleure explication du concept que j'ai trouvée se trouve ici : https://groups.google.com/forum/#!msg/angular/kqFrwiysgpA/eB9mNbQzcHwJ

Pour vous éviter de cliquer :

// get Angular scope from the known DOM element
e = document.getElementById('myAngularApp');
scope = angular.element(e).scope();
// update the model with a wrap in $apply(fn) which will refresh the view for us
scope.$apply(function() {
    scope.controllerMethod(val);
});

13voto

guillaumevincent Points 633

Grâce à l'article précédent, je peux mettre à jour mon modèle avec un événement asynchrone.

<div id="control-panel" ng-controller="Filters">
    <ul>
        <li ng-repeat="filter in filters">
        <button type="submit" value="" class="filter_btn">{{filter.name}}</button>
        </li>
    </ul>
</div>

Je déclare mon modèle

function Filters($scope) {
    $scope.filters = [];
}

Et je mets à jour mon modèle depuis l'extérieur de mon champ d'application

ws.onmessage = function (evt) {
    dictt = JSON.parse(evt.data);
    angular.element(document.getElementById('control-panel')).scope().$apply(function(scope){
        scope.filters = dictt.filters;
    });
};

13voto

Alec Hewitt Points 195

En complément des autres réponses. Si vous ne voulez pas accéder à une méthode dans un contrôleur mais que vous voulez accéder directement au service, vous pouvez faire quelque chose comme ceci :

// Angular code* :
var myService = function(){
    this.my_number = 9;
}
angular.module('myApp').service('myService', myService);

// External Legacy Code:
var external_access_to_my_service = angular.element('body').injector().get('myService');
var my_number = external_access_to_my_service.my_number

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X