¿Cómo accedo a la variable $ scope en la consola del navegador usando AngularJS?

1239

Me gustaría acceder a mi $scopevariable en la consola de JavaScript de Chrome. ¿Cómo puedo hacer eso?

No puedo ver $scopeni el nombre de mi módulo myappen la consola como variables.

murtaza52
fuente
85
Para la depuración, generalmente configuro lo window.MY_SCOPE = $scope;primero en mi función de controlador.
Jason Goemaat
66
Si está considerando desarrollar / probar en Firefox, también puede usar AngScope , una pequeña extensión que muestra $scopeobjetos de elementos DOM seleccionados en el Inspector DOM de Firebug.
Kos Prov
@JasonGoemaat por qué no usar window. $ Scope = $ scope; para que simplemente pueda usar $ scope en lugar de MY_SCOPE: no he notado ningún problema, pero tal vez me estoy perdiendo un problema de seguridad o algo así.
James Gentes
8
Solo por claridad, alguien nuevo en angular podría confundirse y pensar que $ scope estaba mágicamente disponible en la consola si simplemente lo veía así. Además, si por error usa el alcance en una declaración de directiva y $ alcance en el código, por ejemplo, lo usaría en el objeto de la ventana en lugar de obtener un error.
Jason Goemaat

Respuestas:

1759

Elija un elemento en el panel HTML de las herramientas de desarrollador y escriba esto en la consola:

angular.element($0).scope()

En WebKit y Firefox,$0 es una referencia al nodo DOM seleccionado en la pestaña de elementos, por lo que al hacer esto se imprime el alcance del nodo DOM seleccionado en la consola.

También puede orientar el alcance por ID de elemento, así:

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

Complementos / Extensiones

Hay algunas extensiones de Chrome muy útiles que quizás quieras consultar:

  • Batarang . Esto ha existido por un tiempo.

  • ng-inspector . Este es el más nuevo y, como su nombre lo indica, le permite inspeccionar los ámbitos de su aplicación.

Jugando con jsFiddle

Al trabajar con jsfiddle, puede abrir el violín en modo show agregando /showal final de la URL. Cuando se ejecuta así, tiene acceso a la angularglobal. Puedes probarlo aquí:

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

jQuery Lite

Si carga jQuery antes de AngularJS, angular.elementse le puede pasar un selector jQuery. Para que pueda inspeccionar el alcance de un controlador con

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

De un botón

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

... y así.

Es posible que desee utilizar una función global para que sea más fácil:

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

Ahora puedes hacer esto

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

Verifique aquí: http://jsfiddle.net/jaimem/DvRaR/1/show/

jaime
fuente
Gracias. Cuando intento instalar Batarang me dice que su computadora no es compatible, tengo ubuntu, ¿alguna idea?
murtaza52
@ jm- a partir de angular.element($0).scope(), funciona hasta que intente llamar a algunos métodos. Lo intenté y, por alguna razón, ¿no son posibles las solicitudes HTTP en esta configuración?
krtek
41
Tenga en cuenta que si deshabilita la información de depuración, siempre obtendrá indefinidos mediante este método. Esto está previsto y puede evitarse si ... bueno, no deshabilita la información de depuración en $ compileProvider
Robba
66
alternativa a angular.element ($ 0) .scope (): también puede hacer $ ($ 0) .scope ()
user2954463
1
@jaime debería mencionar cómo volver a habilitar el alcance de un elemento cuando se ha desactivado por rendimiento.
enorl76
187

Para mejorar la respuesta 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();

O si está utilizando jQuery, esto hace lo mismo ...

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

Otra forma fácil de acceder a un elemento DOM desde la consola (como se menciona jm) es hacer clic en él en la pestaña 'elementos', y se almacena automáticamente como $0.

angular.element($0).scope();
Simon East
fuente
3
angular contiene un subconjunto de jquery, por lo que siempre puede usar la sintaxis posterior (si es correcta), no estoy seguro de que sea
Pizzaiola Gorgonzola
3
Terminé con angular.element(document.body).scope(), gracias!
Alex Sorokoletov
37

Esta es una forma de llegar al alcance sin Batarang, puede hacer:

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

O si desea encontrar su alcance por nombre de controlador, haga esto:

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

Después de realizar cambios en su modelo, deberá aplicar los cambios al DOM llamando a:

scope.$apply();
BraveNewMath
fuente
44
¿Cómo esta respuesta tiene tantos votos positivos? ¡No necesitas jQuery para esto! angular.elementya es un método de selección de elementos. ¡Deja de decir que necesitas jQuery para tareas simples como seleccionar un elemento por su id!
Kyeotic
3
No dije que lo necesitaras. Lo que estoy diciendo es que si ya lo tienes allí, puedes usarlo así.
BraveNewMath
44
angular.element ya hace lo que estás usando para jQuery. De hecho, si jQuery está disponible angular.elementes un alias para jQuery. Estás innecesariamente complicando tu código. angular.element('#selectorId')y angular.element('[ng-controller=myController]')hacer lo mismo, solo que con menos código. Es lo mismo que llamarangular.element('#selectorId'.toString())
Kyeotic
8
@Tyrsius, ¿quizás tu opinión podría ser menos acusatoria y enojada y un poco más profesional?
Tass
66
@Tass Tienes razón, era innecesariamente grosero. Me disculpo. Es suficiente decir que se está haciendo lo mismo dos veces.
Kyeotic
31

En algún lugar de su controlador (a menudo, la última línea es un buen lugar), coloque

console.log($scope);

Si desea ver un alcance interno / implícito, digamos dentro de una repetición ng, algo como esto funcionará.

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

Luego en tu controlador

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

Tenga en cuenta que anteriormente definimos la función showScope () en el ámbito principal, pero está bien ... el ámbito secundario / interno / implícito puede acceder a esa función, que luego imprime el ámbito en función del evento y, por lo tanto, el ámbito asociado con El elemento que disparó el evento.

La sugerencia de @ jm- también funciona, pero no creo que funcione dentro de un jsFiddle. Me sale este error en jsFiddle dentro de Chrome:

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

Mark Rajcok
fuente
10

Una advertencia para muchas de estas respuestas: si alias tu controlador, tus objetos de alcance estarán en un objeto dentro del objeto devuelto desde scope() .

Por ejemplo, si su directiva de controlador se crea así: <div ng-controller="FormController as frm"> para acceder a una startDatepropiedad de su controlador, debería llamarangular.element($0).scope().frm.startDate

Michael Blackburn
fuente
Se puede acceder al controlador para verlo (por lo tanto, para la consola) como una propiedad de $scope, nombrada $ctrlde manera predeterminada, independientemente de si se cambia el nombre usando controllerAso no. No entiendo dónde viste una "advertencia" en las respuestas existentes. Tenga en cuenta que la mayoría de las respuestas aquí se proporcionaron cuando controllerAsno era una práctica común.
tao
Derecha. Cuando se dieron esas respuestas, controllerAsno era una práctica común, por lo que era confuso para los novatos que podrían haber estado siguiendo un "libro de cocina" que les decía alias al controlador, pero luego no ver las propiedades sin usar el alias. Las cosas se movían rápido hace dos años.
Michael Blackburn
8

Estoy de acuerdo en que lo mejor es Batarang con él $scopedespués de seleccionar un objeto (es lo mismo angular.element($0).scope()o incluso más corto con jQuery: $($0).scope()(mi favorito))

Además, si como yo tiene su alcance principal en el bodyelemento, a $('body').scope()funciona bien.

dorio
fuente
7

Para agregar y mejorar las otras respuestas, en la consola, ingrese $($0) para obtener el elemento. Si se trata de una aplicación Angularjs, se carga una versión jQuery lite de forma predeterminada.

Si no está usando jQuery, puede usar angular.element ($ 0) como en:

angular.element($0).scope()

Para verificar si tiene jQuery y la versión, ejecute este comando en la consola:

$.fn.jquery

Si ha inspeccionado un elemento, el elemento seleccionado actualmente está disponible a través de la referencia de API de línea de comando $ 0. Tanto Firebug como Chrome tienen esta referencia.

Sin embargo, las herramientas de desarrollador de Chrome pondrán a disposición los últimos cinco elementos (u objetos de almacenamiento dinámico) seleccionados a través de las propiedades denominadas $ 0, $ 1, $ 2, $ 3, $ 4 utilizando estas referencias. El elemento u objeto seleccionado más recientemente puede ser referenciado como $ 0, el segundo más reciente como $ 1 y así sucesivamente.

Aquí está la referencia de la API de línea de comandos para Firebug que enumera sus referencias.

$($0).scope()devolverá el alcance asociado con el elemento. Puede ver sus propiedades de inmediato.

Algunas otras cosas que puede usar son:

  • Ver un elemento de alcance primario:

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

  • También puedes encadenar esto:

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

  • Puedes mirar el alcance raíz:

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

  • Si resaltó una directiva con alcance aislado, puede verla con:

$($0).isolateScope()

Consulte Consejos y trucos para depurar código Angularjs desconocido para obtener más detalles y ejemplos.

James Drinkard
fuente
5

Inspeccione el elemento, luego use esto en la consola

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

Simplemente asigne $scopecomo una variable global. Problema resuelto.

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

De hecho, necesitamos $scopemás a menudo en desarrollo que en producción.

Ya lo mencionó @JasonGoemaat pero lo agregó como una respuesta adecuada a esta pregunta.

Sandeep
fuente
4

Lo he usado angular.element($(".ng-scope")).scope();en el pasado y funciona muy bien. Solo es bueno si solo tiene un alcance de aplicación en la página, o puede hacer algo como:

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

Miguel
fuente
3

Por lo general, uso la función jQuery data () para eso:

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

El elemento $ 0 actualmente está seleccionado en el inspector DOM de Chrome. $ 1, $ 2 ... y así sucesivamente son elementos previamente seleccionados.

wojtekc
fuente
2

Digamos que desea acceder al alcance del elemento como

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

Puede usar lo siguiente en la consola:

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

Esto le dará el alcance en ese elemento.

Praym
fuente
1
no necesitamos "document.querySelector" aquí
Stepan Suvorov
1

En la consola 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

Ejemplo

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

Consola de Chrome ingrese la descripción de la imagen aquí

Khachornchit Songsaen
fuente
1

Esto requiere que jQuery también esté instalado, pero funciona perfectamente para un entorno de desarrollo. Mira a través de cada elemento para obtener las instancias de los ámbitos y luego los devuelve etiquetados con los nombres de los controladores. También elimina cualquier propiedad que comience con $, que es lo que angularjs generalmente usa para su configuración.

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
fuente
0

en angular obtenemos el elemento jquery por angular.element () .... vamos a c ...

angular.element().scope();

ejemplo:

<div id=""></div>

Rizo
fuente
0

Solo para fines de depuración pongo esto al inicio del controlador.

   window.scope = $scope;

  $scope.today = new Date();

Y así es como lo uso.

ingrese la descripción de la imagen aquí

luego elimínelo cuando haya terminado de depurar.

mcvkr
fuente
-1

Coloque un punto de interrupción en su código en algún lugar cercano a una referencia a la variable $ scope (para que el $ scope esté en el alcance actual de 'JavaScript antiguo simple'). Luego puede inspeccionar el valor de $ scope en la consola.

Chris Halcrow
fuente
-6

Simplemente defina una variable de JavaScript fuera del alcance y asígnela a su alcance en su controlador:

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

¡Eso es! Debería funcionar en todos los navegadores (probado al menos en Chrome y Mozilla).

Está funcionando y estoy usando este método.

Asqan
fuente
2
Usar variables globales es una mala práctica, pero supongo que está bien en la mayoría de los casos. Es solo para depurar después de todo; Pero aún así debe tener cuidado de no usar el mismo nombre de variable dos veces.
Pedro Affonso
3
Es una mala idea porque requiere que modifiques el código fuente. Esto es molesto incluso si es su propio código, e imposible si es algo que se ejecuta en otro servidor. Incluso si puede modificar el código, debe recordar deshacerlo. Entonces, aunque puede funcionar, no es la mejor práctica.
Jim Davis
1
@JimDavis En general, estoy de acuerdo, pero hay casos en que hacer esto es útil: al modificar temporalmente las fuentes, puede dejar que el código haga las cosas que tendría que hacer manualmente una y otra vez. Entonces, cuando el problema se siente complicado y la depuración llevará mucho tiempo, modifico el código. Deshacer los cambios es trivial con la herramienta adecuada (git).
maaartinus