Angular.js: angular.element.scope() renvoie undefined

Créé le 9 oct. 2014  ·  29Commentaires  ·  Source: angular/angular.js

angular.element.scope() n'est pas défini lorsque l'application est chargée dans iframe en modifiant l'attribut iframe src.

Le code suivant doit renvoyer une référence à la portée mais renvoie undefined :

angular.element(document.body).scope()

Le code ci-dessus est exécuté dans le gestionnaire onclick une fois que le document est chargé et qu'angular a terminé l'amorçage :

<script>
    document.addEventListener("click", function(){
        console.log(angular.element(document.body).scope());
    });
</script>

Le problème ne se manifeste que lorsque le document est chargé dans l'iframe en modifiant son attribut src.
Testé avec 1.3.0-rc.5, sans jquery.

jqLite more info

Commentaire le plus utile

Si vous souhaitez activer temporairement les informations de débogage (par exemple pour déboguer un problème sur une application de production en direct), vous pouvez utiliser angular.reloadWithDebugInfo() comme décrit ici .

Tous les 29 commentaires

Pouvez-vous fournir une reproduction plnkr du problème s'il vous plaît ?

J'ai le même problème dans mon propre projet, mais je ne peux pas le reproduire en utilisant plnkr.

scope() renvoie undefined sur n'importe quel élément.

L'utilisation de JQLite ou JQuery 2.1.1 fait la même chose.

AngularJS 1.3.1.

Essaye ça:

document.addEventListener('DOMContentLoaded', function () {
  angular.element(document.body).scope();
});

désactivez-vous les informations de débogage dans votre projet @VictorQueiroz ?

@caitp Vous l'avez trouvé.

L'activation des informations de débogage est une bonne solution de contournement pour ce problème.

une bonne solution de contournement

:sourire: :sourire: :sourire:

Désolé les gars de ne pas avoir réagi pendant un moment. Le problème est en quelque sorte lié à jqCache, ou plus précisément à la façon dont expandoId est créé. Dans les RC plus anciens, l'identifiant était créé comme ceci :
var expandoId = element[JQLite.expando];
Dans les plus récents, l'identifiant est obtenu à l'aide de la propriété codée en dur :
var expandoId = element.ng339;
L'annulation de la modification a résolu le problème.
Malheureusement, je ne connais pas grand-chose à ce sujet, donc si quelqu'un pouvait faire la lumière sur la fonctionnalité, je serais peut-être en mesure de décrire le problème plus en détail.

Oh wow merci @caitp qui me rendait folle !
Il devrait y avoir une note dans la doc sur le $compileProvider expliquant que $compileProvider.debugInfoEnabled(false) rendra la fonction scope() indéfinie, si c'est le comportement attendu.

Edit : mon mauvais, c'est déjà dans la doc

Appelez cette méthode pour activer/désactiver diverses informations d'exécution de débogage dans le compilateur, telles que l'ajout d'informations de liaison et une référence à la portée actuelle sur les éléments DOM.

Y a-t-il un moyen de contourner ceci; ayant debugInfoEnabled (false), mais étant toujours en mesure d'accéder à la portée d'un élément ?

Si vous souhaitez activer temporairement les informations de débogage (par exemple pour déboguer un problème sur une application de production en direct), vous pouvez utiliser angular.reloadWithDebugInfo() comme décrit ici .

Je pense que @gkalpak a clarifié les choses ici !

Pourquoi fermer ? Trouver une solution de contournement ne signifie pas que le problème est résolu, scope() doit renvoyer la portée attachée quel que soit le mode de débogage.

Si ce n'est pas possible, cela doit être clairement documenté dans angular.element #scope() doc.

@Toilal Je l'ai fermé car il est déjà documenté comme mentionné dans les commentaires précédents de ce fil. Mais si vous pensez que cela devrait également être documenté dans d'autres endroits, un PR serait très apprécié !

Je ne peux pas parce que je ne suis pas sûr que les méthodes de sorcière de angular.element ne fonctionneront pas lors de la désactivation du débogage. scope () bien sûr parce que je l'ai essayé, mais qu'en est-il des autres, comme controller (), injecteur () ...

Après le test, cela n'affecte que scope() et isolateScope(). Je vais les documenter et faire un PR.

Mais existe-t-il un moyen de récupérer la portée d'un élément DOM tout en désactivant les informations de débogage ?

@Toilal - pas vraiment - les informations de portée ont été supprimées car leur exposition a un impact sur les performances - c'est pourquoi elles sont cachées derrière un indicateur de débogage.

Mais il ne serait pas si difficile d'écrire une directive qui pourrait le faire et de la mettre sur les éléments que vous devez vérifier

Merci @pkozlowski-opensource. J'ai ajouté une petite phrase sur scope() et isolateScope() dans la documentation, car il me faut un certain temps pour comprendre pourquoi ces méthodes ne fonctionnaient pas dans mon application.

@ocombe C'est ce que je vais faire, car j'écris un composant d'interface utilisateur et je ne peux pas compter sur scope/isolateScope car le développeur final pourrait désactiver les informations de débogage (comme cela est recommandé).

setTimeout(fonction() {
console.log(angular.element(document.body).scope());
}, 100);

qq 20160115164505

@ronnievdv

Y a-t-il un moyen de contourner ceci; ayant debugInfoEnabled (false), mais étant toujours en mesure d'accéder à la portée d'un élément ?

J'ai utilisé l'extrait de code suivant _(non recommandé)_ dans la fonction link de la définition de la directive.

link: function(scope, element, attrs) {
  var isolatedScope = scope.$$childTail;
}

Existe-t-il un moyen de vérifier si debugInfo a été désactivé ou un indicateur pour cela ?

Depuis l'application, vous pouvez utiliser $compileProvider.debugInfoEnabled() .
Si vous souhaitez déboguer une instance en direct dont les informations de débogage sont désactivées (par exemple, un déploiement de production), vous pouvez appeler angular.reloadWithDebugInfo() depuis la console et il rechargera l'application avec les informations de débogage activées.

@gkalpak Je veux juste vérifier si les informations de débogage sont activées ou non. Un peu comme ça.

if(angular.isDebugInfoEnabled()) {
  // Do something
}

@hemkaran , il n'est toujours pas évident d'où vous voulez le vérifier. Je suppose que depuis l'intérieur de votre application.
Si c'est effectivement le cas, vous pouvez utiliser $compileProvider.debugInfoEnabled() .

@Toilal Avez-vous écrit une directive comme ça? Si oui, cela vous dérangerait-il de partager ? J'ai ce problème en ce moment. Je suppose que je vais trouver une solution, mais avoir un deuxième avis sur la façon de le résoudre ne ferait vraiment pas de mal.
cc @ocombe

Désolé, je n'utilise plus Angular 1 et je n'ai jamais eu à écrire une telle directive (car je n'avais besoin de cette information qu'en mode dev)

J'ai fait ce qui suit. On verra si mes coéquipiers le laisseront passer l'examen :)

function exposeScope() {
    return {
        restrict: 'A',
        link: function(scope, element) {
            element[0].APPNAME = {
                getScope: function() {
                    return scope;
                }
            };
        }
    };
}

return {
        restrict: 'A',
        scope: false,
        link: function(scope, elem) {
            elem.data('$scope', scope);
        }
    };

Vous pouvez également définir $isolateScope sur le même si vous en avez besoin.

Cette page vous a été utile?
0 / 5 - 0 notes