Comment accéder à la variable $ scope dans la console du navigateur à l'aide d'AngularJS?

1240

Je souhaite accéder à ma $scopevariable dans la console JavaScript de Chrome. Comment je fais ça?

Je ne vois $scopeni le nom de mon module myappdans la console sous forme de variables.

murtaza52
la source
85
Pour le débogage, je règle généralement la window.MY_SCOPE = $scope;première chose dans la fonction de mon contrôleur.
Jason Goemaat
6
Si vous envisagez de développer / tester dans Firefox, vous pouvez également utiliser AngScope , une petite extension qui affiche les $scopeobjets des éléments DOM sélectionnés dans l'inspecteur DOM de Firebug.
Kos Prov
@JasonGoemaat pourquoi ne pas utiliser la fenêtre. $ Scope = $ scope; afin que vous puissiez simplement utiliser $ scope plutôt que MY_SCOPE - Je n'ai pas remarqué de problème mais peut-être qu'il me manque un problème de sécurité ou quelque chose.
James Gentes
8
Pour plus de clarté, quelqu'un de nouveau dans angular pourrait être confus et penser que $ scope était magiquement disponible dans la console si on le voyait utilisé de cette façon. De plus, si vous utilisez ensuite par erreur scope dans une déclaration de directive et $ scope dans le code par exemple, vous utiliserez cela sur l'objet window au lieu d'obtenir une erreur.
Jason Goemaat

Réponses:

1760

Choisissez un élément dans le panneau HTML des outils de développement et saisissez-le dans la console:

angular.element($0).scope()

Dans WebKit et Firefox, $0est une référence au nœud DOM sélectionné dans l'onglet Éléments, donc en faisant cela, vous obtenez la portée du nœud DOM sélectionné imprimée dans la console.

Vous pouvez également cibler la portée par ID d'élément, comme ceci:

angular.element(document.getElementById('yourElementId')).scope()

Extensions / extensions

Il existe des extensions Chrome très utiles que vous voudrez peut-être consulter:

  • Batarang . Cela existe depuis un certain temps.

  • ng-inspecteur . C'est le plus récent, et comme son nom l'indique, il vous permet d'inspecter les étendues de votre application.

Jouer avec jsFiddle

Lorsque vous travaillez avec jsfiddle, vous pouvez ouvrir le violon en mode show en ajoutant /showà la fin de l'URL. Lorsque vous exécutez comme ceci, vous avez accès au angularglobal. Vous pouvez l'essayer ici:

http://jsfiddle.net/jaimem/Yatbt/show

jQuery Lite

Si vous chargez jQuery avant AngularJS, vous angular.elementpouvez passer un sélecteur jQuery. Vous pouvez donc inspecter la portée d'un contrôleur avec

angular.element('[ng-controller=ctrl]').scope()

D'un bouton

 angular.element('button:eq(1)').scope()

... etc.

Vous voudrez peut-être utiliser une fonction globale pour le rendre plus facile:

window.SC = function(selector){
    return angular.element(selector).scope();
};

Maintenant tu peux faire ça

SC('button:eq(10)')
SC('button:eq(10)').row   // -> value of scope.row

Vérifiez ici: http://jsfiddle.net/jaimem/DvRaR/1/show/

jaime
la source
Merci. Lorsque j'essaie d'installer Batarang, il me dit que votre ordinateur n'est pas pris en charge, j'ai Ubuntu, des idées?
murtaza52
@ jm- à partir de angular.element($0).scope(), cela fonctionne jusqu'à ce que vous essayiez d'appeler certaines méthodes. J'ai essayé, et pour une raison quelconque, aucune demande HTTP n'est possible dans cette configuration?
krtek
41
Notez que si vous désactivez les informations de débogage, vous serez toujours indéfini en utilisant cette méthode. Ceci est prévu et peut être évité en ... eh bien, en ne désactivant pas les informations de débogage sur $ compileProvider
Robba
6
alternative à angular.element ($ 0) .scope (): vous pouvez également faire $ ($ 0) .scope ()
user2954463
1
@jaime doit mentionner comment réactiver l'obtention de la portée d'un élément lorsqu'il a été désactivé pour des performances.
enorl76
187

Pour améliorer la réponse de jm ...

// Access whole scope
angular.element(myDomElement).scope();

// Access and change variable in scope
angular.element(myDomElement).scope().myVar = 5;
angular.element(myDomElement).scope().myArray.push(newItem);

// Update page to reflect changed variables
angular.element(myDomElement).scope().$apply();

Ou si vous utilisez jQuery, cela fait la même chose ...

$('#elementId').scope();
$('#elementId').scope().$apply();

Un autre moyen facile d'accéder à un élément DOM à partir de la console (comme l'a mentionné jm) consiste à cliquer dessus dans l'onglet «Éléments», et il est automatiquement stocké sous $0.

angular.element($0).scope();
Simon East
la source
3
angular contient un sous-ensemble de jquery, vous pouvez donc toujours utiliser la syntaxe ultérieure (si elle est correcte), je ne suis pas sûr que ce soit
Pizzaiola Gorgonzola
3
Je me suis retrouvé avec angular.element(document.body).scope(), merci!
Alex Sorokoletov
37

C'est un moyen de se rendre à portée sans Batarang, vous pouvez faire:

var scope = angular.element('#selectorId').scope();

Ou si vous souhaitez trouver votre portée par nom de contrôleur, procédez comme suit:

var scope = angular.element('[ng-controller=myController]').scope();

Après avoir apporté des modifications à votre modèle, vous devrez appliquer les modifications au DOM en appelant:

scope.$apply();
BraveNewMath
la source
4
Comment cette réponse a-t-elle autant de votes positifs? Vous n'avez pas besoin de jQuery pour cela! angular.elementest déjà une méthode de sélection d'élément. Arrêtez de dire que vous avez besoin de jQuery pour des tâches simples comme la sélection d'un élément par son identifiant!
Kyeotic
3
Je n'ai pas dit que tu en avais besoin. Ce que je dis, c'est que si vous l'avez déjà là, vous pouvez l'utiliser comme ça.
BraveNewMath
4
angular.element fait déjà la chose pour laquelle vous utilisez jQuery. En fait, si jQuery est disponible, angular.elementc'est un alias pour jQuery. Vous compliquez inutilement votre code. angular.element('#selectorId')et angular.element('[ng-controller=myController]')faites la même chose, mais avec moins de code. Vous pourriez aussi bien appelerangular.element('#selectorId'.toString())
Kyeotic
8
@Tyrsius, vos commentaires pourraient être moins accusateurs et en colère et un peu plus professionnels?
Tass du
6
@Tass Tu as raison, j'étais inutilement grossier. Je m'excuse. Il suffit de dire que la même chose se fait deux fois.
Kyeotic
31

Quelque part dans votre contrôleur (souvent la dernière ligne est un bon endroit), mettez

console.log($scope);

Si vous voulez voir une portée interne / implicite, disons à l'intérieur d'une répétition ng, quelque chose comme ça fonctionnera.

<li ng-repeat="item in items">
   ...
   <a ng-click="showScope($event)">show scope</a>
</li>

Puis dans votre manette

function MyCtrl($scope) {
    ...
    $scope.showScope = function(e) {
        console.log(angular.element(e.srcElement).scope());
    }
}

Notez que ci-dessus, nous définissons la fonction showScope () dans la portée parent, mais ce n'est pas grave ... la portée enfant / intérieure / implicite peut accéder à cette fonction, qui imprime ensuite la portée en fonction de l'événement, et donc la portée associée à l'élément qui a déclenché l'événement.

La suggestion de @ jm- fonctionne également, mais je ne pense pas que cela fonctionne à l'intérieur d'un jsFiddle. Je reçois cette erreur sur jsFiddle dans Chrome:

> angular.element($0).scope()
ReferenceError: angular is not defined

Mark Rajcok
la source
10

Une mise en garde à plusieurs de ces réponses: si vous alias votre contrôleur, vos objets de portée se trouveront dans un objet de l'objet renvoyé scope().

Par exemple, si votre directive contrôleur est créée comme ceci: <div ng-controller="FormController as frm"> alors pour accéder à une startDatepropriété de votre contrôleur, vous appelleriezangular.element($0).scope().frm.startDate

Michael Blackburn
la source
Le contrôleur est accessible pour voir (donc pour console) comme une propriété de $scope, nommé $ctrlpar défaut, indépendamment du fait que vous le renommiez en utilisant controllerAsou non. Je ne comprends pas où vous avez vu une "mise en garde" dans les réponses existantes. Notez que la plupart des réponses ici ont été fournies alors que ce controllerAsn'était pas une pratique courante.
tao
Droite. Lorsque ces réponses ont été données, ce controllerAsn'était pas une pratique courante, donc c'était déroutant pour les débutants qui suivaient peut-être un "livre de cuisine" qui leur disait d'alias le contrôleur, mais de ne pas voir les propriétés sans utiliser l'alias. Les choses allaient vite il y a deux ans.
Michael Blackburn
8

Je suis d'accord que le meilleur est Batarang avec c'est $scopeaprès avoir sélectionné un objet (c'est le même angular.element($0).scope()ou même plus court avec jQuery: $($0).scope()(mon préféré))

De plus, si comme moi vous avez votre portée principale sur l' bodyélément, cela $('body').scope()fonctionne très bien.

Dorian
la source
7

Pour ajouter et améliorer les autres réponses, dans la console, entrez $($0)pour obtenir l'élément. S'il s'agit d'une application Angularjs, une version jQuery lite est chargée par défaut.

Si vous n'utilisez pas jQuery, vous pouvez utiliser angular.element ($ 0) comme dans:

angular.element($0).scope()

Pour vérifier si vous avez jQuery et la version, exécutez cette commande dans la console:

$.fn.jquery

Si vous avez inspecté un élément, l'élément actuellement sélectionné est disponible via la référence d'API de ligne de commande $ 0. Firebug et Chrome ont cette référence.

Cependant, les outils de développement Chrome rendront disponibles les cinq derniers éléments (ou objets de tas) sélectionnés via les propriétés nommées $ 0, $ 1, $ 2, $ 3, $ 4 en utilisant ces références. L'élément ou l'objet sélectionné le plus récemment peut être référencé comme $ 0, le deuxième plus récent comme $ 1 et ainsi de suite.

Voici la référence de l'API de ligne de commande pour Firebug qui répertorie ses références.

$($0).scope()retournera la portée associée à l'élément. Vous pouvez voir ses propriétés tout de suite.

Certaines autres choses que vous pouvez utiliser sont:

  • Afficher la portée parent d'un élément:

$($0).scope().$parent.

  • Vous pouvez également l'enchaîner:

$($0).scope().$parent.$parent

  • Vous pouvez regarder la portée racine:

$($0).scope().$root

  • Si vous avez mis en surbrillance une directive avec une portée isolée, vous pouvez la consulter avec:

$($0).isolateScope()

Voir Trucs et astuces pour déboguer le code Angularjs inconnu pour plus de détails et d'exemples.

James Drinkard
la source
5

Inspectez l'élément, puis utilisez-le dans la console

s = $($0).scope()
// `s` is the scope object if it exists
geg
la source
5

Attribuez simplement $scopeune variable globale. Problème résolu.

app.controller('myCtrl', ['$scope', '$http', function($scope, $http) {
    window.$scope = $scope;
}

Nous avons en fait besoin $scopeplus souvent en développement qu'en production.

Mentionné déjà par @JasonGoemaat mais en l'ajoutant comme réponse appropriée à cette question.

Sandeep
la source
4

Je l'ai utilisé angular.element($(".ng-scope")).scope();dans le passé et cela fonctionne très bien. Ce n'est bon que si vous n'avez qu'une seule étendue d'application sur la page, ou si vous pouvez faire quelque chose comme:

angular.element($("div[ng-controller=controllerName]")).scope(); ou angular.element(document.getElementsByClassName("ng-scope")).scope();

Mike
la source
3

J'utilise généralement la fonction jQuery data () pour cela:

$($0).data().$scope

L'élément $ 0 est actuellement sélectionné dans l'inspecteur DOM Chrome. $ 1, $ 2 .. et ainsi de suite sont des éléments précédemment sélectionnés.

wojtekc
la source
2

Supposons que vous souhaitiez accéder à la portée de l'élément comme

<div ng-controller="hw"></div>

Vous pouvez utiliser les éléments suivants dans la console:

angular.element(document.querySelector('[ng-controller=hw]')).scope();

Cela vous donnera la portée de cet élément.

Praym
la source
1
nous n'avons pas besoin de "document.querySelector" ici
Stepan Suvorov
1

Sur la console de Chrome:

 1. Select the **Elements** tab
 2. Select the element of your angular's scope. For instance, click on an element <ui-view>, or <div>, or etc.
 3. Type the command **angular.element($0).scope()** with following variable in the angular's scope

Exemple

angular.element($0).scope().a
angular.element($0).scope().b

Console de Chrome entrez la description de l'image ici

Khachornchit Songsaen
la source
1

Cela nécessite que jQuery soit également installé, mais fonctionne parfaitement pour un environnement de développement. Il examine chaque élément pour obtenir les instances des étendues, puis les renvoie étiquetées avec leurs noms de contrôleur. Il supprime également toute propriété commençant par un $, ce que angularjs utilise généralement pour sa configuration.

let controllers = (extensive = false) => {
            let result = {};
            $('*').each((i, e) => {
                let scope = angular.element(e).scope();
                if(Object.prototype.toString.call(scope) === '[object Object]' && e.hasAttribute('ng-controller')) {
                    let slimScope = {};
                    for(let key in scope) {
                        if(key.indexOf('$') !== 0 && key !== 'constructor' || extensive) {
                            slimScope[key] = scope[key];
                        }
                    }
                    result[$(e).attr('ng-controller')] = slimScope;
                }
            });

            return result;
        }
Luke Pring
la source
0

en angulaire on obtient l'élément jquery par angular.element () .... laisse c ...

angular.element().scope();

exemple:

<div id=""></div>

Rizo
la source
0

À des fins de débogage uniquement, je mets cela au début du contrôleur.

   window.scope = $scope;

  $scope.today = new Date();

Et c'est comme ça que je l'utilise.

entrez la description de l'image ici

puis supprimez-le lorsque j'ai terminé le débogage.

mcvkr
la source
-1

Placez un point d'arrêt dans votre code à un endroit proche d'une référence à la variable $ scope (de sorte que $ scope se trouve dans la portée 'plain old JavaScript'). Ensuite, vous pouvez inspecter la valeur $ scope dans la console.

Chris Halcrow
la source
-6

Définissez simplement une variable JavaScript en dehors de la portée et affectez-la à votre portée dans votre contrôleur:

var myScope;
...
app.controller('myController', function ($scope,log) {
     myScope = $scope;
     ...

C'est ça! Il devrait fonctionner dans tous les navigateurs (testé au moins dans Chrome et Mozilla).

Cela fonctionne, et j'utilise cette méthode.

Asqan
la source
2
L'utilisation de variables globales est une mauvaise pratique, mais je suppose que c'est correct dans la plupart des cas. C'est seulement pour le débogage après tout; Mais vous devez toujours faire attention à ne pas utiliser deux fois le même nom de variable.
Pedro Affonso
3
C'est une mauvaise idée car elle vous oblige à modifier le code source. C'est ennuyeux même si c'est votre propre code, et impossible si c'est quelque chose qui s'exécute sur un autre serveur. Même si vous pouvez modifier le code, vous devez alors vous rappeler de l'annuler. Donc, même si cela peut fonctionner, ce n'est pas la meilleure pratique.
Jim Davis
1
@JimDavis En général, je suis d'accord, mais il y a des cas où cela est utile: En modifiant temporairement les sources, vous pouvez laisser le code faire ce que vous devez faire manuellement encore et encore. Donc, lorsque le problème semble délicat et que le débogage va prendre du temps, je modifie le code. Annuler les modifications est trivial avec le bon outil (git).
maaartinus