Come posso accedere alla variabile $ scope nella console del browser usando AngularJS?


1239

Vorrei accedere alla mia $scopevariabile nella console JavaScript di Chrome. Come lo faccio?

Non riesco a vedere $scopené il nome del mio modulo myappnella console come variabili.


85
Per il debug di solito imposto la window.MY_SCOPE = $scope;prima cosa nella funzione del mio controller.
Jason Goemaat,

6
Se stai considerando lo sviluppo / test in Firefox, puoi anche usare AngScope , una piccola estensione che mostra gli $scopeoggetti degli elementi DOM selezionati in DOM Inspector di Firebug.
Kos Prov

@JasonGoemaat perché non usare window. $ Scope = $ scope; così puoi semplicemente usare $ scope piuttosto che MY_SCOPE - non ho notato alcun problema ma forse mi manca un problema di sicurezza o qualcosa del genere.
James Gentes,

8
Solo per chiarezza, qualcuno che non conosce angolare potrebbe confondersi e pensare che $ scope fosse magicamente disponibile nella console se l'avesse appena visto essere usato in quel modo. Inoltre, se si utilizza erroneamente l'ambito in una dichiarazione di direttiva e $ scope nel codice, ad esempio, lo si utilizzerà sull'oggetto window invece di ottenere un errore.
Jason Goemaat,

Risposte:


1759

Scegli un elemento nel pannello HTML degli strumenti di sviluppo e digita questo nella console:

angular.element($0).scope()

In WebKit e Firefox, $0è un riferimento al nodo DOM selezionato nella scheda degli elementi, quindi in questo modo si ottiene l'ambito del nodo DOM selezionato stampato nella console.

Puoi anche scegliere come target l'ambito per ID elemento, in questo modo:

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

Addons / Estensioni

Ci sono alcune estensioni di Chrome molto utili che potresti voler controllare:

  • Batarang . Questo è in circolazione da un po '.

  • ng-inspector . Questo è il più recente e, come suggerisce il nome, consente di ispezionare gli ambiti dell'applicazione.

Giocare con jsFiddle

Quando lavori con jsfiddle puoi aprire il violino in modalità show aggiungendo /showalla fine dell'URL. Quando corri in questo modo hai accesso al angularglobale. Puoi provarlo qui:

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

jQuery Lite

Se si carica jQuery prima di AngularJS, è angular.elementpossibile passare un selettore jQuery. Quindi è possibile ispezionare l'ambito di un controller con

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

Di un pulsante

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

... e così via.

Potresti effettivamente voler utilizzare una funzione globale per semplificare:

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

Ora potresti farlo

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

Controlla qui: http://jsfiddle.net/jaimem/DvRaR/1/show/


Grazie. Quando provo ad installare Batarang mi dice che il tuo computer non è supportato, ho Ubuntu, qualche idea?
murtaza52,

@ jm- a partire da angular.element($0).scope(), funziona fino a quando non si tenta di chiamare alcuni metodi. Ho provato e per qualche motivo non sono possibili richieste HTTP in questa configurazione?
Krtek,

41
Si noti che se si disabilitano le informazioni di debug si ottiene sempre indefinito utilizzando questo metodo. Questo è previsto e può essere prevenuto da ... .well, non disabilitando le informazioni di debug su $ compileProvider
Robba

6
alternativa a angular.element ($ 0) .scope (): potresti anche fare $ ($ 0) .scope ()
user2954463

1
@jaime dovrebbe menzionare come riattivare l'ottenimento dell'ambito da un elemento quando è stato spento per le prestazioni.
enorl76,

187

Per migliorare la risposta di 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();

O se stai usando jQuery, questo fa la stessa cosa ...

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

Un altro modo semplice per accedere a un elemento DOM dalla console (come menzionato jm) è fare clic su di esso nella scheda "elementi" e viene automaticamente archiviato come $0.

angular.element($0).scope();

3
angular contiene un sottoinsieme di jquery, quindi puoi sempre usare la sintassi successiva (se è corretta), non sono sicuro che sia
Pizzaiola Gorgonzola

3
Ho finito con angular.element(document.body).scope(), grazie!
Alex Sorokoletov,


37

Questo è un modo per arrivare all'ambito senza Batarang, puoi fare:

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

Oppure, se si desidera trovare l'ambito in base al nome del controller, procedere come segue:

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

Dopo aver apportato modifiche al tuo modello, dovrai applicare le modifiche al DOM chiamando:

scope.$apply();

4
In che modo questa risposta ha tanti voti positivi? Non hai bisogno di jQuery per questo! angular.elementè già un metodo di selezione degli elementi. Smetti di dire che hai bisogno di jQuery per attività semplici come la selezione di un elemento tramite il suo ID!
Kyeotic,

3
Non ho detto che ne hai bisogno. Quello che sto dicendo è che se lo hai già lì potresti usarlo in questo modo.
BraveNewMath,

4
angular.element fa già la cosa per cui stai usando jQuery. In effetti, se jQuery è disponibile angular.elementè un alias per jQuery. Stai inutilmente complicando il tuo codice. angular.element('#selectorId')e angular.element('[ng-controller=myController]')fare la stessa cosa, solo con meno codice. Potresti anche chiamareangular.element('#selectorId'.toString())
Kyeotic il

8
@Tyrsius, forse il tuo feedback potrebbe essere meno accusatorio e arrabbiato e un po 'più professionale?
Tass

6
@Tass Hai ragione, ero inutilmente scortese. Chiedo scusa. Basta dire che la stessa cosa viene fatta due volte.
Kyeotic,

31

Da qualche parte nel tuo controller (spesso l'ultima riga è un buon posto), metti

console.log($scope);

Se vuoi vedere un ambito interno / implicito, per esempio all'interno di una ripetizione ng, qualcosa del genere funzionerà.

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

Quindi nel controller

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

Si noti che sopra definiamo la funzione showScope () nell'ambito genitore, ma va bene ... l'ambito figlio / interno / implicito può accedere a quella funzione, che quindi stampa l'ambito in base all'evento e quindi l'ambito associato a l'elemento che ha generato l'evento.

Anche il suggerimento di @ jm- funziona, ma non credo che funzioni all'interno di un jsFiddle. Ottengo questo errore su jsFiddle in Chrome:

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


10

Un avvertimento per molte di queste risposte: se si alias il controller, gli oggetti scope saranno in un oggetto all'interno dell'oggetto restituito scope().

Ad esempio, se la direttiva del controller viene creata in questo modo: <div ng-controller="FormController as frm"> per accedere a una startDateproprietà del controller, si chiamerebbeangular.element($0).scope().frm.startDate


Il controller è accessibile per essere visualizzato (quindi da console) come una proprietà di $scope, denominata $ctrlper impostazione predefinita, indipendentemente dal fatto che lo si rinomini usando controllerAso meno. Non capisco dove hai visto un "avvertimento" nelle risposte esistenti. Nota che la maggior parte delle risposte qui sono state fornite quando controllerAsnon era una pratica comune.
Tao,

Giusto. Quando venivano fornite quelle risposte, controllerAsnon era pratica comune, quindi era confuso per i neofiti che avrebbero potuto seguire un "libro di cucina" che diceva loro di alias il controller, ma poi non vedevano le proprietà senza usare l'alias. Le cose si stavano muovendo velocemente due anni fa.
Michael Blackburn,

8

Concordo sul fatto che Batarang sia il migliore $scopedopo aver selezionato un oggetto (è uguale angular.element($0).scope()o anche più breve con jQuery: $($0).scope()(il mio preferito))

Inoltre, se come me hai l'ambito principale bodysull'elemento, $('body').scope()funziona benissimo.


7

Per aggiungere e migliorare le altre risposte, nella console, immettere $($0)per ottenere l'elemento. Se si tratta di un'applicazione Angularjs, per impostazione predefinita viene caricata una versione jQuery Lite.

Se non si utilizza jQuery, è possibile utilizzare angular.element ($ 0) come in:

angular.element($0).scope()

Per verificare se hai jQuery e la versione, esegui questo comando nella console:

$.fn.jquery

Se hai ispezionato un elemento, l'elemento attualmente selezionato è disponibile tramite il riferimento API della riga di comando $ 0. Sia Firebug che Chrome hanno questo riferimento.

Tuttavia, gli strumenti di sviluppo di Chrome renderanno disponibili gli ultimi cinque elementi (o oggetti heap) selezionati tramite le proprietà denominate $ 0, $ 1, $ 2, $ 3, $ 4 utilizzando questi riferimenti. L'elemento o l'oggetto selezionato più di recente può essere indicato come $ 0, il secondo più recente come $ 1 e così via.

Ecco il riferimento API della riga di comando per Firebug che elenca i suoi riferimenti.

$($0).scope()restituirà l'ambito associato all'elemento. Puoi vedere subito le sue proprietà.

Alcune altre cose che puoi usare sono:

  • Visualizza un ambito padre elementi:

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

  • Puoi anche concatenare questo:

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

  • Puoi vedere l'ambito radice:

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

  • Se hai evidenziato una direttiva con ambito isolato, puoi guardarla con:

$($0).isolateScope()

Vedi Suggerimenti e trucchi per il debug del codice Angularjs non familiare per maggiori dettagli ed esempi.


5

Ispeziona l'elemento, quindi utilizzalo nella console

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

5

Basta assegnare $scopecome variabile globale. Problema risolto.

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

In realtà abbiamo bisogno $scopepiù spesso di sviluppo che di produzione.

Menzionato già da @JasonGoemaat ma aggiungendolo come risposta adatta a questa domanda.


4

Ho usato angular.element($(".ng-scope")).scope();in passato e funziona benissimo. Buono solo se hai un solo ambito di app sulla pagina o puoi fare qualcosa del tipo:

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


3

Di solito uso la funzione jQuery data () per questo:

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

$ 0 è attualmente l'elemento selezionato nella finestra di ispezione DOM di Chrome. $ 1, $ 2 .. e così via sono elementi precedentemente selezionati.


2

Supponiamo che tu voglia accedere all'ambito dell'elemento like

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

È possibile utilizzare quanto segue nella console:

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

Questo ti darà l'ambito di quell'elemento.


1
non abbiamo bisogno di "document.querySelector" qui
Stepan Suvorov,

1

Alla console di 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

Esempio

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

Console di Chrome inserisci qui la descrizione dell'immagine


1

Ciò richiede l'installazione anche di jQuery, ma funziona perfettamente per un ambiente di sviluppo. Esamina ogni elemento per ottenere le istanze degli ambiti, quindi le restituisce etichettate con i nomi dei controller. Rimuove anche qualsiasi proprietà che inizia con $ che è ciò che generalmente usa angularjs per la sua configurazione.

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;
        }

0

in angolare otteniamo l'elemento jquery da angular.element () .... lascia che c ...

angular.element().scope();

esempio:

<div id=""></div>


0

A solo scopo di debug ho messo questo all'inizio del controller.

   window.scope = $scope;

  $scope.today = new Date();

Ed è così che lo uso.

inserisci qui la descrizione dell'immagine

quindi eliminarlo al termine del debug.


-1

Inserisci un punto di interruzione nel codice in un punto vicino a un riferimento alla variabile $ scope (in modo che l'ambito $ si trovi nell'attuale ambito "semplicemente vecchio JavaScript"). Quindi è possibile controllare il valore $ scope nella console.


-6

Basta definire una variabile JavaScript al di fuori dell'ambito e assegnarla al proprio ambito nel controller:

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

Questo è tutto! Dovrebbe funzionare in tutti i browser (testato almeno in Chrome e Mozilla).

Funziona e sto usando questo metodo.


2
L'uso di variabili globali è una cattiva pratica, ma credo che nella maggior parte dei casi vada bene. Dopotutto è solo per il debug; Tuttavia, devi stare attento a non utilizzare lo stesso nome di variabile due volte.
Pedro Affonso,

3
È una cattiva idea perché richiede di modificare il codice sorgente. Questo è fastidioso anche se è il tuo codice e impossibile se è qualcosa in esecuzione su un altro server. Anche se è possibile modificare il codice, è necessario ricordare di annullarlo. Quindi, sebbene possa funzionare, non è la migliore pratica.
Jim Davis,

1
@JimDavis In generale sono d'accordo, ma ci sono casi in cui ciò è utile: modificando temporaneamente le fonti puoi lasciare che il codice faccia le cose che dovresti fare manualmente ancora e ancora. Quindi, quando il problema sembra complicato e il debug richiederà molto tempo, modifico il codice. Annullare le modifiche è banale con lo strumento giusto (git).
maaartinus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.