Como acesso a variável $ scope no console do navegador usando o AngularJS?

1239

Gostaria de acessar minha $scopevariável no console JavaScript do Chrome. Como faço isso?

Não consigo ver $scopenem o nome do meu módulo myappno console como variáveis.

murtaza52
fonte
85
Para depuração, geralmente defino a window.MY_SCOPE = $scope;primeira coisa na minha função de controlador.
Jason Goemaat
6
Se você está pensando em desenvolver / testar no Firefox, também pode usar o AngScope , uma pequena extensão que exibe $scopeobjetos de elementos DOM selecionados no DOM Inspector do Firebug.
Kos Prov
@JasonGoemaat, por que não usar window. $ Scope = $ scope; para que você possa simplesmente usar $ scope em vez de MY_SCOPE - eu não notei nenhum problema, mas talvez esteja faltando uma preocupação de segurança ou algo assim.
James Gentes
8
Apenas para maior clareza, alguém novo no angular pode ficar confuso e pensar que $ scope estava magicamente disponível no console se apenas o visse sendo usado dessa maneira. Além disso, se você usar o escopo por engano em uma declaração de diretiva e $ scope no código, por exemplo, o usaria no objeto window em vez de obter um erro.
21430 Jason Malaio

Respostas:

1759

Escolha um elemento no painel HTML das ferramentas do desenvolvedor e digite isso no console:

angular.element($0).scope()

No WebKit e Firefox, $0é uma referência ao nó DOM selecionado na guia elementos. Dessa forma, você obtém o escopo do nó DOM selecionado impresso no console.

Você também pode direcionar o escopo pelo ID do elemento, da seguinte maneira:

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

Complementos / extensões

Existem algumas extensões úteis do Chrome que você pode querer conferir:

  • Batarang . Isso já existe há algum tempo.

  • Inspetor de ng . Este é o mais novo e, como o nome sugere, permite que você inspecione os escopos do seu aplicativo.

Tocando com jsFiddle

Ao trabalhar com o jsfiddle, você pode abrir o violino no modo de exibição adicionando /showno final da URL. Ao executar assim, você tem acesso ao angularglobal. Você pode tentar aqui:

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

jQuery Lite

Se você carregar o jQuery antes do AngularJS, angular.elementpoderá receber um seletor de jQuery. Então você pode inspecionar o escopo de um controlador com

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

De um botão

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

... e assim por diante.

Você pode realmente querer usar uma função global para facilitar:

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

Agora você pode fazer isso

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

Verifique aqui: http://jsfiddle.net/jaimem/DvRaR/1/show/

jaime
fonte
Obrigado. Quando tento instalar o Batarang, ele diz que seu computador não é suportado, tenho o ubuntu, alguma idéia?
murtaza52
@ jm- a partir de angular.element($0).scope(), ele funciona até você tentar chamar alguns métodos. Eu tentei e, por algum motivo, nenhuma solicitação HTTP é possível nessa configuração?
krtek
41
Observe que, se você estiver desabilitando as informações de depuração, sempre será indefinido usando esse método. Isso é planejado e pode ser evitado por ... bem, não desabilitando as informações de depuração no $ compileProvider
Robba
6
alternativa ao angular.element ($ 0) .scope (): você também pode fazer $ ($ 0) .scope ()
user2954463
1
O @jaime deve mencionar como reativar a obtenção de escopo de um elemento quando este estiver desativado para desempenho.
enorl76
187

Para melhorar a resposta do 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 se você estiver usando jQuery, isso faz a mesma coisa ...

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

Outra maneira fácil de acessar um elemento DOM do console (como jm mencionado) é clicar nele na guia 'elementos', e ele é automaticamente armazenado como $0.

angular.element($0).scope();
Simon East
fonte
3
angular contém um subconjunto de jQuery, assim você sempre pode usar a sintaxe mais tarde (se é correto), eu não tenho certeza que ele é
Pizzaiola Gorgonzola
3
Acabei com angular.element(document.body).scope(), obrigado!
Alex Sorokoletov
37

Esta é uma maneira de chegar ao escopo sem o Batarang, você pode fazer:

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

Ou se você deseja encontrar seu escopo pelo nome do controlador, faça o seguinte:

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

Depois de fazer alterações no seu modelo, você precisará aplicar as alterações no DOM chamando:

scope.$apply();
BraveNewMath
fonte
4
Como essa resposta tem tantos votos positivos? Você não precisa do jQuery para isso! angular.elementjá é um método de seleção de elemento. Pare de dizer que você precisa do jQuery para tarefas simples, como selecionar um elemento pelo seu ID!
Kyeotic
3
Eu não disse que você precisa disso. O que estou dizendo é que se você já o tiver, poderá usá-lo assim.
BraveNewMath
4
angular.element já faz o que você está usando jQuery. De fato, se o jQuery estiver disponível, angular.elementé um alias para o jQuery. Você está desnecessariamente complicando seu código. angular.element('#selectorId')e angular.element('[ng-controller=myController]')faça a mesma coisa, apenas com menos código. Você também pode ligarangular.element('#selectorId'.toString())
Kyeotic
8
@ Tyrsius, talvez seu feedback possa ser menos acusador e irritado e um pouco mais profissional?
Tass
6
@Tass Você está certo, eu fui desnecessariamente rude. Peço desculpas. Basta dizer que a mesma coisa está sendo feita duas vezes.
Kyeotic
31

Em algum lugar do seu controlador (geralmente a última linha é um bom lugar), coloque

console.log($scope);

Se você quiser ver um escopo interno / implícito, digamos, dentro de um ng-repeat, algo como isso funcionará.

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

Então no seu controlador

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

Observe que, acima, definimos a função showScope () no escopo pai, mas tudo bem ... o escopo filho / interno / implícito pode acessar essa função, que depois imprime o escopo com base no evento e, portanto, o escopo associado a o elemento que disparou o evento.

A sugestão de @ jm- também funciona, mas não acho que funcione dentro de um jsFiddle. Recebo este erro no jsFiddle dentro do Chrome:

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

Mark Rajcok
fonte
10

Uma ressalva para muitas dessas respostas: se você alias seu controlador, seus objetos de escopo estarão em um objeto dentro do objeto retornado de scope().

Por exemplo, se sua diretiva de controlador for criada assim: <div ng-controller="FormController as frm"> para acessar uma startDatepropriedade do seu controlador, você chamariaangular.element($0).scope().frm.startDate

Michael Blackburn
fonte
O Controller é acessível para visualizar (daí para o console) como uma propriedade $scopenomeada $ctrlpor padrão, independentemente de você renomeá-lo usando controllerAsou não. Não entendo onde você viu uma "advertência" nas respostas existentes. Observe que a maioria das respostas aqui foram fornecidas quando controllerAsnão era uma prática comum.
tao
Direita. Quando essas respostas foram dadas, controllerAsnão era uma prática comum, por isso era confuso para iniciantes que talvez estivessem seguindo um "livro de receitas" que lhes dizia para usar o pseudônimo do controlador, mas depois não ver as propriedades sem usar o pseudônimo. As coisas estavam mudando rápido há dois anos.
Michael Blackburn
8

Eu concordo que o melhor é Batarang $scopedepois de selecionar um objeto (é o mesmo angular.element($0).scope()ou mais curto com o jQuery: $($0).scope()(meu favorito))

Além disso, se como eu, você tem o escopo principal do bodyelemento, $('body').scope()funciona bem.

Dorian
fonte
7

Para adicionar e aprimorar as outras respostas, no console, digite $($0)para obter o elemento. Se for um aplicativo Angularjs, uma versão jQuery lite é carregada por padrão.

Se você não estiver usando jQuery, poderá usar angular.element ($ 0) como em:

angular.element($0).scope()

Para verificar se você possui jQuery e a versão, execute este comando no console:

$.fn.jquery

Se você inspecionou um elemento, o elemento atualmente selecionado estará disponível através da referência da API da linha de comandos $ 0. O Firebug e o Chrome têm essa referência.

No entanto, as ferramentas de desenvolvedor do Chrome disponibilizarão os últimos cinco elementos (ou objetos de heap) selecionados através das propriedades denominadas $ 0, $ 1, $ 2, $ 3, $ 4 usando essas referências. O elemento ou objeto selecionado mais recentemente pode ser referenciado como $ 0, o segundo mais recente como $ 1 e assim por diante.

Aqui está a referência da API da linha de comando do Firebug que lista suas referências.

$($0).scope()retornará o escopo associado ao elemento. Você pode ver suas propriedades imediatamente.

Algumas outras coisas que você pode usar são:

  • Exibir um escopo pai de elementos:

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

  • Você também pode encadear isso:

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

  • Você pode olhar para o escopo raiz:

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

  • Se você destacou uma diretiva com escopo isolado, pode ver com:

$($0).isolateScope()

Consulte Dicas e truques para depurar código Angularjs não familiar para obter mais detalhes e exemplos.

James Drinkard
fonte
5

Inspecione o elemento e use-o no console

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

Apenas atribua $scopecomo uma variável global. Problema resolvido.

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

Na verdade, precisamos $scopemais frequentemente de desenvolvimento do que de produção.

Já mencionado por @JasonGoemaat, mas adicioná-lo como uma resposta adequada a esta pergunta.

Sandeep
fonte
4

Eu usei angular.element($(".ng-scope")).scope();no passado e funciona muito bem. Só é bom se você tiver apenas um escopo de aplicativo na página ou se puder fazer algo como:

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

Mike
fonte
3

Eu normalmente uso a função jQuery data () para isso:

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

O item $ 0 está atualmente selecionado no inspetor DOM do chrome. $ 1, $ 2 ... e assim por diante são itens selecionados anteriormente.

wojtekc
fonte
2

Digamos que você queira acessar o escopo do elemento como

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

Você pode usar o seguinte no console:

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

Isso fornecerá o escopo desse elemento.

Praym
fonte
1
não precisamos de "document.querySelector" aqui
Stepan Suvorov
1

No console do 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

Exemplo

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

Console do Chrome insira a descrição da imagem aqui

Khachornchit Songsaen
fonte
1

Isso requer que o jQuery seja instalado também, mas funciona perfeitamente para um ambiente de desenvolvimento. Ele examina cada elemento para obter as instâncias dos escopos e depois as rotula com os nomes dos controladores. A remoção de qualquer propriedade também começa com um $, que é o que angularjs geralmente usa para sua configuração.

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

em angular, obtemos o elemento jquery por angular.element () .... permite c ...

angular.element().scope();

exemplo:

<div id=""></div>

Rizo
fonte
0

Apenas para fins de depuração, coloquei isso no início do controlador.

   window.scope = $scope;

  $scope.today = new Date();

E é assim que eu uso.

insira a descrição da imagem aqui

exclua-o quando terminar a depuração.

mcvkr
fonte
-1

Coloque um ponto de interrupção no seu código em um local próximo à referência à variável $ scope (para que o $ scope esteja no escopo atual do 'JavaScript antigo simples'). Em seguida, você pode inspecionar o valor de escopo $ no console.

Chris Halcrow
fonte
-6

Apenas defina uma variável JavaScript fora do escopo e atribua-a ao seu escopo no seu controlador:

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

É isso aí! Ele deve funcionar em todos os navegadores (testados pelo menos no Chrome e Mozilla).

Está funcionando e estou usando esse método.

Asqan
fonte
2
Usar variáveis ​​globais é uma prática ruim, mas acho que isso é bom na maioria dos casos. Afinal, é apenas para depuração; Mas você precisa ter cuidado para não usar o mesmo nome de variável duas vezes.
Pedro Affonso
3
É uma péssima idéia, pois exige que você modifique o código-fonte. Isso é irritante, mesmo que seja seu próprio código, e impossível se for algo em execução em outro servidor. Mesmo que você possa modificar o código, lembre-se de desfazê-lo. Portanto, embora possa funcionar, não é a melhor prática.
Jim Davis
1
@ JimDavis Em geral, eu concordo, mas há casos em que isso é útil: modificando temporariamente as fontes, você pode deixar o código fazer as coisas que você teria que fazer manualmente repetidamente. Então, quando o problema parecer complicado e a depuração demorar, eu modifico o código. Desfazer as alterações é trivial com a ferramenta correta (git).
maaartinus 8/09/16