Как получить доступ к переменной $ scope в консоли браузера с помощью AngularJS?

1240

Я хотел бы получить доступ к моей $scopeпеременной в консоли Chrome JavaScript. Как я могу это сделать?

Я не могу видеть $scopeни имя моего модуля myappв консоли в качестве переменных.

murtaza52
источник
85
Для отладки я обычно устанавливаю window.MY_SCOPE = $scope;первое в своей функции контроллера.
Джейсон Гомаат
6
Если вы рассматриваете разработку / тестирование в Firefox, вы также можете использовать AngScope , небольшое расширение, которое отображает $scopeобъекты выбранных элементов DOM в DOM-инспекторе Firebug.
Кос Пров
@JasonGoemaat, почему бы не использовать окно. $ Scope = $ scope; так что вы можете просто использовать $ scope вместо MY_SCOPE - я не заметил никаких проблем, но, возможно, я пропускаю проблему безопасности или что-то в этом роде.
Джеймс Гентес
8
Просто для ясности, кто-то новичок в angular может запутаться и подумать, что $ scope магически доступен в консоли, если только что видел, как он используется таким образом. Кроме того, если вы затем по ошибке используете область действия в объявлении директивы и, например, $ scope в коде, вы будете использовать это в объекте окна вместо получения ошибки.
Джейсон Гомаат

Ответы:

1760

Выберите элемент на панели HTML инструментов разработчика и введите его в консоли:

angular.element($0).scope()

В WebKit и Firefox $0это ссылка на выбранный узел DOM на вкладке элементов, поэтому, выполнив это, вы получите область выбранного узла DOM, распечатанную в консоли.

Вы также можете нацелить область видимости по идентификатору элемента, например так:

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

Плагины / расширения

Есть несколько очень полезных расширений Chrome, которые вы можете попробовать:

  • Batarang . Это было вокруг некоторое время.

  • нг-инспектор . Это новейшая версия, и, как следует из названия, она позволяет вам осмотреть области своего приложения.

Играя с jsFiddle

При работе с jsfiddle вы можете открыть скрипку в режиме показа , добавив /showв конце URL. Когда вы работаете так, у вас есть доступ к angularглобальному. Вы можете попробовать это здесь:

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

JQuery Lite

Если вы загружаете jQuery до AngularJS, angular.elementможет быть передан селектор jQuery. Таким образом, вы можете проверить область действия контроллера с

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

Кнопки

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

... и так далее.

Возможно, вы захотите использовать глобальную функцию, чтобы упростить ее:

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

Теперь вы можете сделать это

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

Проверьте здесь: http://jsfiddle.net/jaimem/DvRaR/1/show/

Хайме
источник
Спасибо. Когда я пытаюсь установить Batarang, он говорит, что ваш компьютер не поддерживается, у меня есть Ubuntu, есть идеи?
Murtaza52
@ jm- с того angular.element($0).scope()момента, пока не попробуешь вызвать некоторые методы. Я пытался, и по какой-то причине никакие запросы HTTP невозможны в этой настройке?
krtek
41
Обратите внимание, что если вы отключите отладочную информацию, вы всегда получите неопределенный, используя этот метод. Это предназначено и может быть предотвращено с помощью… .well, не отключая отладочную информацию на $ compileProvider
Robba
6
альтернатива angular.element ($ 0) .scope (): вы также можете сделать $ ($ 0) .scope ()
user2954463
1
@jaime должен упомянуть, как повторно включить получение области из элемента, когда он был отключен для производительности.
enorl76
187

Чтобы улучшить ответ 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();

Или, если вы используете JQuery, это делает то же самое ...

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

Другой простой способ получить доступ к элементу DOM из консоли (как упоминалось в jm) - щелкнуть по нему во вкладке «elements», и он автоматически сохранится как $0.

angular.element($0).scope();
Саймон Ист
источник
3
angular содержит подмножество jquery, поэтому вы всегда можете использовать более поздний синтаксис (если он правильный), я не уверен, что это так
Pizzaiola Gorgonzola
3
Я закончил с angular.element(document.body).scope(), спасибо!
Алексей Сороколетов
37

Это способ достичь цели без Batarang, вы можете сделать:

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

Или, если вы хотите найти свою область по имени контроллера, сделайте это:

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

После того, как вы внесете изменения в свою модель, вам нужно применить изменения к DOM, вызвав:

scope.$apply();
BraveNewMath
источник
4
Откуда у этого ответа столько голосов? Вам не нужен jQuery для этого! angular.elementэто уже метод выбора элемента. Перестаньте говорить, что вам нужен jQuery для простых задач, таких как выбор элемента по его идентификатору!
Kyeotic
3
Я не говорил, что тебе это нужно. То, что я говорю, если у вас уже есть это, вы можете использовать это так.
BraveNewMath
4
angular.element уже делает то, что вы используете для jQuery. Фактически, если jQuery доступен angular.element, это псевдоним для jQuery. Вы без необходимости усложняете свой код. angular.element('#selectorId')и angular.element('[ng-controller=myController]')делать то же самое, только с меньшим количеством кода. Вы можете также позвонитьangular.element('#selectorId'.toString())
Kyeotic
8
@ Tyrsius, возможно, ваш отзыв может быть менее обвинительным и сердитым, а также более профессиональным?
ТАСС
6
@ Tass Вы правы, я был излишне груб. Приношу извинения. Достаточно сказать, что одно и то же делается дважды.
Kyeotic
31

Где-то в вашем контроллере (часто последняя строка - хорошее место), поставьте

console.log($scope);

Если вы хотите увидеть внутреннюю / неявную область, скажем, внутри ng-repeat, что-то вроде этого будет работать.

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

Тогда в вашем контроллере

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

Обратите внимание, что выше мы определяем функцию showScope () в родительской области, но это нормально ... дочерняя / внутренняя / неявная область может получить доступ к этой функции, которая затем распечатывает область, основанную на событии, и, следовательно, область, связанную с элемент, который вызвал событие.

Предложение @ jm- также работает, но я не думаю, что оно работает внутри jsFiddle. Я получаю эту ошибку на jsFiddle внутри Chrome:

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

Марк Райкок
источник
10

Один из предостережений для многих из этих ответов: если вы используете псевдоним вашего контроллера, ваши объекты области видимости будут в объекте в возвращаемом объекте из scope() .

Например, если ваша директива контроллера создана следующим образом: <div ng-controller="FormController as frm"> для доступа к startDateсвойству вашего контроллера вы должны вызватьangular.element($0).scope().frm.startDate

Майкл Блэкберн
источник
Контроллер является доступным для просмотра (следовательно , к консоли) как свойство $scope, с именем $ctrlпо умолчанию, независимо от переименовывать ли с помощью controllerAsили нет. Я не понимаю, где вы видели «предостережение» в существующих ответах. Обратите внимание, что большинство ответов здесь были предоставлены тогда, когда controllerAsэто не было обычной практикой.
дао
Правильно. Когда эти ответы были даны, controllerAsэто не было обычной практикой, поэтому это было сбивающим с толку для новичков, которые, возможно, следовали «кулинарной книге», в которой указывалось псевдоним контроллера, но затем не видели свойства без использования псевдонима. Все шло быстро два года назад.
Майкл Блэкберн
8

Я согласен, что лучше всего Batarang $scopeпосле выбора объекта (он такой же angular.element($0).scope()или даже короче с jQuery:$($0).scope() (мой любимый))

Кроме того, если, как и я, у вас есть основная сфера действия bodyэлемента, то все $('body').scope()отлично работает.

Дориан
источник
7

Чтобы добавить и улучшить другие ответы, в консоли введите $($0) чтобы получить элемент. Если это приложение Angularjs, по умолчанию загружается версия jQuery lite.

Если вы не используете jQuery, вы можете использовать angular.element ($ 0), как в:

angular.element($0).scope()

Чтобы проверить, есть ли у вас jQuery и версия, выполните эту команду в консоли:

$.fn.jquery

Если вы проверили элемент, текущий выбранный элемент доступен через API-интерфейс командной строки $ 0. И Firebug, и Chrome имеют эту ссылку.

Однако инструменты разработчика Chrome сделают доступными последние пять элементов (или объектов кучи), выбранных через свойства с именами $ 0, $ 1, $ 2, $ 3, $ 4, используя эти ссылки. На последний выбранный элемент или объект можно ссылаться как на $ 0, второй на последний - на $ 1 и так далее.

Вот ссылка API командной строки для Firebug котором перечислены его ссылки.

$($0).scope()вернет область, связанную с элементом. Вы можете увидеть его свойства сразу.

Некоторые другие вещи, которые вы можете использовать:

  • Просмотр родительской области элементов:

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

  • Вы также можете связать это:

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

  • Вы можете посмотреть на корневую область:

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

  • Если вы выделили директиву с изолированной областью действия, вы можете посмотреть на нее:

$($0).isolateScope()

См. Советы и рекомендации по отладке незнакомого кода Angularjs для получения дополнительной информации и примеров.

Джеймс Дринкард
источник
5

Осмотрите элемент, затем используйте это в консоли

s = $($0).scope()
// `s` is the scope object if it exists
ГЕГ
источник
5

Просто назначьте $scopeв качестве глобальной переменной. Задача решена.

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

Нам на самом деле нужно $scopeчаще в разработке, чем в производстве.

Упоминается уже @JasonGoemaat, но добавляет его как подходящий ответ на этот вопрос.

Sandeep
источник
4

Я использовал angular.element($(".ng-scope")).scope();в прошлом, и это прекрасно работает. Хорошо только если у вас есть только одна область приложения на странице, или вы можете сделать что-то вроде:

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

Майк
источник
3

Я обычно использую функцию jQuery data () для этого:

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

В настоящее время выбранный элемент $ 0 в инспекторе Chrome DOM. $ 1, $ 2 .. и т. Д. Являются ранее выбранными элементами.

wojtekc
источник
2

Скажем, вы хотите получить доступ к области действия элемента, как

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

Вы можете использовать следующее в консоли:

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

Это даст вам область действия в этом элементе.

Praym
источник
1
нам здесь не нужен «document.querySelector»
Степан Суворов
1

На консоли 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

пример

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

Консоль Chrome введите описание изображения здесь

Хачорнчит Songsaen
источник
1

Это также требует установки jQuery, но отлично работает для среды разработки. Он просматривает каждый элемент, чтобы получить экземпляры областей, а затем возвращает их, помеченные именами контроллеров. Также удаляется любое свойство, начинающееся с $, которое angularjs обычно использует для своей конфигурации.

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

в угловых мы получаем элемент jquery angular.element () .... позволяет с ...

angular.element().scope();

пример:

<div id=""></div>

Ризо
источник
0

Только для целей отладки я поместил это в начало контроллера.

   window.scope = $scope;

  $scope.today = new Date();

И вот как я это использую.

введите описание изображения здесь

затем удалите его, когда я закончу отладку.

mcvkr
источник
-1

Поместите точку останова в своем коде где-то рядом со ссылкой на переменную $ scope (так, чтобы область действия $ находилась в текущей области видимости «старого старого JavaScript»). Затем вы можете проверить значение $ scope в консоли.

Крис Хэлкроу
источник
-6

Просто определите переменную JavaScript за пределами области и назначьте ее своей области в вашем контроллере:

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

Это оно! Должно работать во всех браузерах (проверено хотя бы в Chrome и Mozilla).

Это работает, и я использую этот метод.

Asqan
источник
2
Использование глобальных переменных - плохая практика, но я думаю, что в большинстве случаев это нормально. Это только для отладки в конце концов; Но все же вы должны быть осторожны, чтобы не использовать одно и то же имя переменной дважды.
Педро Аффонсо
3
Это плохая идея, потому что она требует от вас изменения исходного кода. Это раздражает, даже если это ваш собственный код, и невозможно, если что-то работает на другом сервере. Даже если вы можете изменить код, вы должны помнить, чтобы отменить его. Так что, хотя это может работать, это не лучшая практика.
Джим Дэвис
1
@JimDavis В целом я согласен, но бывают случаи, когда это полезно: временно изменяя исходные коды, вы можете позволить коду делать то, что вам придется делать вручную снова и снова. Поэтому, когда проблема кажется сложной и отладка займет много времени, я модифицирую код. Отменить изменения тривиально с помощью правильного инструмента (git).
Maaartinus