J'utilise AngularJS pour créer des contrôles HTML qui interagissent avec une application Flex héritée. Tous les rappels de l'application Flex doivent être attachés à la fenêtre DOM.
Par exemple (en AS3)
ExternalInterface.call("save", data);
Appellera
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 peut entendre. Il semble que la création d'un service soit la voie à suivre. Pouvez-vous mettre à jour un service depuis l'extérieur d'AngularJS? Un contrôleur peut-il écouter les événements d'un service? Dans une expérience (cliquez pour violon) j'ai fait, il semble que je puisse accéder à un service, mais la mise à jour des données du service ne se reflète pas dans la vue (dans l'exemple, un <option>
devrait être ajouté au <select>
).
Merci!
var injector = angular.injector(['ng', 'MyApp']);
. Cela vous donnera un tout nouveau contexte et un doublonmyService
. Cela signifie que vous vous retrouverez avec deux instances du service et du modèle et que vous ajouterez des données au mauvais endroit. Vous devez plutôt cibler un élément de l'application à l'aide deangular.element('#ng-app').injector(['ng', 'MyApp'])
. À ce stade, vous pouvez ensuite utiliser $ apply pour encapsuler les modifications de modèle.Réponses:
L'interopérabilité de l'extérieur d'angle à angulaire est identique au débogage d'une application angulaire ou à l'intégration avec une bibliothèque tierce.
Pour tout élément DOM, vous pouvez le faire:
angular.element(domElement).scope()
pour obtenir la portée actuelle de l'élémentangular.element(domElement).injector()
pour obtenir l'injecteur d'application actuelangular.element(domElement).controller()
pour mettre la main sur l'ng-controller
instance.Depuis l'injecteur, vous pouvez accéder à n'importe quel service en application angulaire. De la même manière, à partir de la portée, vous pouvez invoquer toutes les méthodes qui y ont été publiées.
Gardez à l'esprit que toute modification du modèle angulaire ou toute invocation de méthode sur la portée doit être enveloppée
$apply()
comme suit:la source
[ng-app]
nœud racine semble à l'envers alors que j'ai déjà une référence au module ...angular.element(document.getElementById(divName)).scope()
, mais je ne suis pas en mesure d'invoquer des fonctions à partir de celui-ci, il renvoie simplement "undefined" dans la console.Misko a donné la bonne réponse (évidemment), mais certains d'entre nous, les débutants, peuvent avoir besoin de la simplifier davantage.
Lorsqu'il s'agit d'appeler du code AngularJS à partir d'applications héritées, considérez le code AngularJS comme une «micro application» existant dans un conteneur protégé de votre application héritée. Vous ne pouvez pas lui faire d'appels directement (pour une très bonne raison), mais vous pouvez faire des appels à distance via 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 HTML "micro-application" AngularJS pour obtenir le handle de l'application $ scope AngularJS.
À titre d'exemple, disons que nous voulons appeler quelques fonctions dans notre contrôleur AngularJS telles que sayHi () et sayBye (). Dans le HTML AngularJS (vue), nous avons un div avec l'id "MySuperAwesomeApp". Vous pouvez utiliser le code suivant, combiné avec jQuery pour obtenir le handle de $ scope:
Vous pouvez maintenant appeler vos fonctions de code AngularJS via le handle de portée:
Pour rendre les choses plus pratiques, vous pouvez utiliser une fonction pour saisir la poignée de la portée à chaque fois que vous souhaitez y accéder:
Vos appels ressembleraient alors à ceci:
Vous pouvez voir un exemple fonctionnel ici:
http://jsfiddle.net/peterdrinnan/2nPnB/16/
J'ai également montré cela dans un diaporama pour le groupe Ottawa AngularJS (passez simplement aux 2 dernières diapositives)
http://www.slideshare.net/peterdrinnan/angular-for-legacyapps
la source
<input type="button" onclick="angular.element(this).scope().edit.delete();" value="delete">
La plus grande explication du concept que j'ai trouvée se trouve ici: https://groups.google.com/forum/#!msg/angular/kqFrwiysgpA/eB9mNbQzcHwJ
Pour vous épargner le clic:
la source
id
dans l'élément HTML supérieur, puis fairedocument.getElementById()
cet identifiant. Cela vous donne accès à la portée de ce contrôleur. méthodes / propriétés etc ... juste mettre un point fin sur le commentaire de goosemanjack.Suite aux autres réponses. Si vous ne souhaitez pas accéder à une méthode dans un contrôleur mais souhaitez accéder directement au service, vous pouvez faire quelque chose comme ceci:
la source
Grâce au post précédent, je peux mettre à jour mon modèle avec un événement asynchrone.
Je déclare mon modèle
Et je mets à jour mon modèle hors de ma portée
la source
Un moyen plus sûr et plus performant, en particulier lorsque les données de débogage sont désactivées, consiste à utiliser une variable partagée pour contenir une fonction de rappel. Votre contrôleur angulaire implémente cette fonction pour renvoyer ses composants internes au code externe.
Généralisée en tant que directive réutilisable:
J'ai créé une directive 'exposeScope' qui fonctionne de la même manière mais l'utilisation est plus simple:
Cela stocke la portée actuelle (qui est donnée à la fonction de lien de la directive) dans un objet global «scopes» qui est un support pour toutes les portées. La valeur fournie à l'attribut de directive est utilisée comme nom de propriété de la portée dans cet objet global.
Voir la démo ici . Comme je l'ai montré dans la démo, vous pouvez déclencher des événements jQuery lorsque la portée est stockée et supprimée de l'objet global 'scopes'.
Notez que je n'ai pas testé le on ('scopeDestroyed') lorsque l'élément réel est supprimé du DOM. Si cela ne fonctionne pas, déclencher l'événement sur le document lui-même au lieu de l'élément peut aider. (voir le script app.js) dans le plunker de démonstration.
la source
Je sais que c'est une vieille question, mais je cherchais des options pour le faire récemment, alors j'ai pensé mettre mes conclusions ici au cas où cela serait utile à quiconque.
Dans la plupart des cas, s'il est nécessaire que du code hérité externe interagisse avec l'état de l'interface utilisateur ou le fonctionnement interne de l'application, un service peut être utile pour résumer ces modifications. Si un code externe interagit directement avec votre contrôleur angulaire, composant ou directive, vous associez fortement votre application à votre code hérité, ce qui est une mauvaise nouvelle.
Ce que j'ai fini par utiliser dans mon cas, c'est une combinaison de globaux accessibles par navigateur (ie fenêtre) et de gestion d'événements. Mon code a un moteur de génération de formulaires intelligent qui nécessite une sortie JSON d'un CMS pour initier les formulaires. Voici ce que j'ai fait:
Le service de schéma de formulaire est créé à l'aide d'un injecteur angulaire comme prévu:
Et dans mes contrôleurs: function () {'use strict';
Jusqu'à présent, il s'agit d'une programmation orientée service angulaire et javascript pure. Mais l'intégration héritée vient ici:
De toute évidence, chaque approche a ses avantages et ses inconvénients. Les avantages et l'utilisation de cette approche dépendent de votre interface utilisateur. Les approches suggérées précédemment ne fonctionnent pas dans mon cas car mon schéma de formulaire et mon code hérité n'ont aucun contrôle et aucune connaissance des portées angulaires. Par conséquent, la configuration de mon application en fonction de
angular.element('element-X').scope();
pourrait potentiellement casser l'application si nous changeons les portées autour. Mais si votre application connaît la portée et peut compter sur elle pour ne pas changer souvent, ce qui a été suggéré précédemment est une approche viable.J'espère que cela t'aides. Tout commentaire est également le bienvenu.
la source