селектор angular.element vs document.getElementById або jQuery з керуванням спином (зайнято)


157

Я використовую "Angularized" версію управління Spin, як це задокументовано тут: http://blog.xvitcoder.com/adding-a-weel-progress-indicator-to-your-angularjs-application/

Одне з речей, яке мені не подобається у показаному рішенні, - це використання jQuery в сервісі, який ефективно прикріплює спін-контроль до елемента DOM. Я б вважав за краще використовувати кутові конструкції для доступу до елемента. Я також хотів би уникати "жорсткого кодування" ідентифікатора елемента, до якого спінеру потрібно прикріпити службу, а замість цього використати директиву, яка встановлює ідентифікатор в службі (синглтон), щоб інші користувачі служби або самому сервісу цього не потрібно знати.

Я борюся з тим, що angular.element дає нам проти того, що document.getElementById у тому самому ідентифікаторі елемента дає нам. напр. Це працює:

  var target = document.getElementById('appBusyIndicator');

Нічого з цього не робить:

  var target = angular.element('#appBusyIndicator');
  var target = angular.element('appBusyIndicator');

Я чітко роблю щось, що має бути досить очевидним неправильним! Чи може хтось допомогти?

Якщо припустити, що я можу отримати вищезгадане, у мене є аналогічна проблема зі спробою замінити доступ jQuery до елемента: наприклад, $(target).fadeIn('fast'); працює angular.element('#appBusyIndicator').fadeIn('fast')чи angular.element('appBusyIndicator').fadeIn('fast')ні

Чи може хтось вказати мені на хороший приклад документації, що пояснює використання кутового "елемента" проти елемента DOM? Кутовий, очевидно, «обгортає» елемент своїми властивостями, методами тощо, але часто важко отримати початкове значення. Наприклад, якщо у мене є <input type='number'>поле і я хочу отримати доступ до оригінального вмісту, який видно в інтерфейсі користувача, коли користувач вводить "-" (без лапок), я нічого не отримую, імовірно, тому що "type = number" означає, що Angular відкидає вхід, незважаючи на те, що його видно в інтерфейсі, і я хочу його бачити, щоб я міг перевірити його та очистити.

Будь-які вказівки / відповіді високо оцінені.

Дякую.


5
angular.element - об’єкт jQlite або об’єкт jQuery, якщо ви завантажуєте jQuery.
Ніл

Відповіді:


226

Це може працювати так:

var myElement = angular.element( document.querySelector( '#some-id' ) );

Ви перетворюєте в дзвінок Document.querySelector()нативний Javascript - angular.element()дзвінок. Таким чином, ви завжди отримуєте елемент в об'єкті jqLite або jQuery , залежно від того jQuery, доступний / завантажений чи ні .

Офіційна документація на angular.element:

Якщо jQuery доступний, angular.elementце псевдонім для jQueryфункції. Якщо jQuery недоступний, angular.elementделегує вбудовану підмножину Angular s jQuery, що називається "jQuery lite" або jqLite .

Всі посилання на Angularелементи завжди обгорнуті jQuery або jqLite(наприклад, аргумент елемента в директиві компіляції або функції зв’язку). Вони ніколи не є сировинними DOMпосиланнями.

Якщо вам цікаво, навіщо користуватися document.querySelector(), прочитайте цю відповідь .


41
Будь-яка причина вважає за краще document.querySelector ('# ...') просто використовувати document.getElementById ()?
Като

4
Ви також можете зробити це на кутовому елементі: var elDivParent = angular.element (elem [0] .querySelector ('# an-id')) ;, elem - кутовий елемент. Таким чином ви можете шукати всередині елемента. Корисно для одиничних тестів.
unludo

4
@Kato Більше інформації у цій відповіді . Сподіваюся, що це допомагає.
кайзер

роботи з Google Maps API, і це спрацювало: var autocomplete = new google.maps.places.Autocomplete( $document[0].querySelector('#address'), { types: ['geocode'], componentRestrictions: {country: 'us'} } );. Дякую за пораду @kaiser. Чомусь карти api скаржилися, що те, що я передав у першому парамі, не є входом, коли я використовував angular.element(document.querySelector('#address')), але все добре, що закінчується добре.
nymo

49

Ви повинні прочитати документи кутового елемента, якщо ви ще цього не зробили, тож ви зможете зрозуміти, що підтримується jqLite, а що ні, -jqlite - це підмножина jquery, вбудованого у angular.

Ці селектори не працюватимуть лише з jqLite, оскільки селектори за допомогою id не підтримуються.

  var target = angular.element('#appBusyIndicator');
  var target = angular.element('appBusyIndicator');

Отже, або:

  • ви використовуєте jqLite в поодинці, більш обмежений, ніж jquery, але достатній у більшості ситуацій.
  • або ви включаєте повну вкладку jQuery у свій додаток і використовуєте її як звичайний jquery в місцях, де вам справді потрібен jquery.

Редагувати: Зауважте, що jQuery слід завантажувати перед angularJS, щоб мати перевагу над jqLite:

Справжня jQuery завжди має перевагу над jqLite, за умови, що вона була завантажена до запуску події DOMContentLoaded.

Edit2: Я пропустив другу частину питання раніше:

Проблема з <input type="number">, я думаю, це не кутова проблема, це призначена поведінка нативного елемента html5.

Він не поверне нечислове значення, навіть якщо ви спробуєте отримати його за допомогою jquery's .val()або з необробленим .valueатрибутом.


2
У нас є повна бібліотека jQuery - інакше мій сценарій $ пояснений вище не працював. У мене було питання, чому $ працює, але angular.element не працює - навіть незважаючи на те, що доступний повний jQuery.
irascian

1
Ви включаєте jQuery до або після angular.js? Він повинен бути включений перед кутовим. Селектори за ідентифікатором зробити роботу з JQuery доступним: jsbin.com/ohumiy/1/edit
Гарст

1
Вони працюють в іншій директиві (наприклад, angular.element, щоб отримати доступ до чогось за id). Здається, проблема полягає в тому, як працює цей елемент управління, приєднуючись до цього елемента, хоча я не розумію, чому той самий jQuery еквівалент повинен працювати безпосередньо. Використовуючи jQuery безпосередньо, моя директива МАЄ мати тег закриття - тег, що самозамикається, не працює (немає помилок, просто порожній екран), що змушує мене підозрювати управління.
irascian

2
У моєму другому пункті також є щось на кшталт view $ value, яке може бути використане для отримання вмісту елемента, але у випадку типу input = число, де користувач має введення "-" це порожнє. Я хочу властивість на зразок $ rawInputValue на елементі, щоб побачити вміст перед тим, як Angular вступив, тому що "-" все ще знаходиться в інтерфейсі, хоча я не маю доступу до нього програмно в моїх директивах.
irascian

27
var target = document.getElementById('appBusyIndicator');

дорівнює

var target = $document[0].getElementById('appBusyIndicator');

1
Краще скористатись другим прикладом, щоб переконатися, що ваші залежності є явними і з них можна глузувати, правда?
Лука

так і має бути, але я думаю, що в кутовій 2+ ми просто більше покладаємось на функції машинопису. Більше не потрібно турбуватися про ці речі :)
Дасун

17

Я не думаю, що це правильний спосіб використання кутового. Якщо рамковий метод не існує, не створюйте його! Це означає, що рамка (тут кутова) не працює таким чином.

За допомогою кутового ви не повинні маніпулювати DOM таким чином (спосіб jquery), а використовувати кутовий помічник типу

<div ng-show="isLoading" class="loader"></div>

Або створити власну директиву (власний компонент DOM), щоб мати повний контроль над нею.

До речі, ви можете побачити тут http://caniuse.com/#search=queryselector querySelector добре підтримується, тому його можна безпечно використовувати.


2
Ви абсолютно праві. 90% + випадків, які, на мою думку, потрібно вручну маніпулювати DOM, я закінчив рефакторинг коду, щоб усунути необхідність, і врешті-решт код набагато чистіший.
Стівен Чун

17

Якщо хтось використовує gulp, він показує помилку, якщо ми використовуємо, document.getElementById()і він пропонує використовувати, $document.getElementById()але він не працює.

Використання -

$document[0].getElementById('id')

Чому сюди вводять кутовий масив?
Петро

16

Ви можете отримати доступ до елементів за допомогою $ document ($ document потрібно ввести)

var target = $document('#appBusyIndicator');
var target = $document('appBusyIndicator');

або з кутовим елементом, доступ до зазначених елементів можна отримати як:

var targets = angular.element(document).find('div'); //array of all div
var targets = angular.element(document).find('p');
var target = angular.element(document).find('#appBusyIndicator');

1
find () - Обмежено для пошуку за назвою тегів
RJV

angular.element (document) .find ('. someClass'); працює прекрасно.
Нішант Баранваль

10

Вам слід ввести $ документ у свій контролер і використовувати його замість оригінального об'єкта документа.

var myElement = angular.element($document[0].querySelector('#MyID'))

Якщо вам не потрібна обробка елементів стилю jquery, $ document [0] .querySelector ('# MyID') надасть вам об’єкт DOM.


1
Ви також можете просто посилатися на window.document безпосередньо замість того, щоб використовувати накладні послуги Angulars $.
MatBee

5
Звичайно, ви можете, якщо ви не
переймаєтесь

Мені не зрозуміло: я отримую цей попередження: Вам слід скористатися службою документу $ замість об'єкта документа за замовчуванням, але що це означає? Будь-які документи про це? Дякую!
реальноне

@realnot Ви можете отримати доступ до документу HTML DOM-об'єкта з будь-якого місця вашого javascript. w3schools.com/jsref/dom_obj_document.asp
Адамі

6

Це добре працювало для мене.

angular.forEach(element.find('div'), function(node)
{
  if(node.id == 'someid'){
    //do something
  }
  if(node.className == 'someclass'){
    //do something
  }
});

3
елемент не визначений? angular.element.find - це не функція для мене, яка пробує вашу без JQuery.
приземлився

3
Будь ласка, не робіть цього. Скористайтеся одним із інших прикладів. Тут взагалі не використовуються оптимізації пошуку хеш-таблиць.
MatBee

4

Вдосконалення відповіді кайзера:

var myEl = $document.find('#some-id');

Не забудьте ввести $documentсвою директиву


21
Як зазначалося в кутовій документації для element.find :, find() - Limited to lookups by tag nameвін не працює на ідентифікатори. Також у вас є додаткове закриття ).
пааат

3

Можливо, я тут занадто пізно, але це спрацює:

var target = angular.element(appBusyIndicator);

Зауважте, немає appBusyIndicator, це звичайне значення ідентифікатора.

Що відбувається за лаштунками: (якщо припустити, що він застосований у діві) (взято з рядка angular.js №: 2769 далі ...)

/////////////////////////////////////////////
function JQLite(element) {     //element = div#appBusyIndicator
  if (element instanceof JQLite) {
    return element;
  }

  var argIsString;

  if (isString(element)) {
    element = trim(element);
    argIsString = true;
  }
  if (!(this instanceof JQLite)) {
    if (argIsString && element.charAt(0) != '<') {
      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
    }
    return new JQLite(element);
  }

За замовчуванням, якщо на сторінці немає jQuery, буде використовуватися jqLite. Аргумент внутрішньо розуміється як ідентифікатор, і відповідний об'єкт jQuery повертається.


Я спробував це зараз з кутовим 1.5.8. Простий ідентифікатор повертає порожній результат. angular.element("#myId")працює добре.
Гоша У.

можливо у вас є jQuery на своїй сторінці?
Вішал Ананд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.