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

Я використовую версію керування Spin "Angularised", як це описано тут: 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') не

Can someone point me to a good example of documentation that clarifies use of an Angular "element" vs the DOM element? Angular obviously "wraps" the element with its own properties, methods etc but it's often hard to get the original value. For example if I have an <input type='number'> field and I want to access the original contents that are visible in the ui when the user types "--" (without the quotes) I get nothing, presumably because the "type=number" means Angular is rejecting the input even though it's visible in the UI and I want to see it so I can test for it and clear it down.

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

Дякую.

133
angular.element це об'єкт jQlite або jQuery об'єкт, якщо ви завантажуєте jQuery.
додано Автор Neil, джерело

10 Відповіді

Він може працювати так:

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 делегує вбудовану підмножину jQuery Angular , яка називається "jQuery Lite" або jqLite .

     

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

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

203
додано
З будь-якої причини ви хотіли б вказати документ.querySelector ('# ...'), щоб просто використовувати document.getElementById ()?
додано Автор Kato, джерело
@ Като Більше інформації в цю відповідь . Надія, що допомагає.
додано Автор kaiser, джерело
Ви також можете зробити це за кутовим елементом: var elDivParent = angular.element (elem [0] .querySelector ('# an-id')) ;, елемент є кутовим елементом. Таким чином, ви можете шукати всередині елемента. Корисно для одиничних тестів.
додано Автор unludo, джерело
працюючи з API Google Maps, і це працювало: var autocomplete = new google.maps.places.Autocomplete ($ document [0] .querySelector ('# address'), {types: ['geocode'], componentRestrictions: {country: 'us'}}); . Дякую за відгук @kaiser. З деяких причин карти api скаржилися на те, що те, що я передав у першому параметрі, не було введенням, коли я використав angular.element (document.querySelector ('# address')) , але все добре, що закінчується добре.
додано Автор nymo, джерело

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

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

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

Отже:

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

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

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

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

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

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

44
додано
Ви включаєте jQuery до або після angular.js? Він повинен бути включений перед кутовий. Селектори за id роблять працювати з jQuery доступними: jsbin.com/ohumiy/1/ редагувати
додано Автор gargc, джерело
На моєму 2-му тобі також є щось подібне до перегляду $ value, яке можна використовувати для вилучення вмісту елемента, але у випадку типу вводу = номер, де користувач має введення "-", це порожнє значення. Я хочу мати властивість щось на кшталт $ rawInputValue на елементі, щоб побачити вміст, перш ніж Angular ввійшов, тому що "-" все ще знаходиться в інтерфейсі користувача, навіть якщо в моїй директиві я не маю доступу до нього програмно.
додано Автор irascian, джерело
Вони працюють в іншій директиві (тобто кутовий елемент для доступу до ідентифікатора). Схоже, проблема полягає в тому, як цей контроль працює, приєднуючись до цього елементу, хоча я і не розумію, чому саме такий же еквівалентний jQuery повинен працювати. Використовуючи jQuery безпосередньо, моя директива повинна мати закритий тег - сам закриваючий тег не працює (без помилок просто чистий екран), що змушує мене підозрювати контроль.
додано Автор irascian, джерело
У нас є повна бібліотека jQuery - інакше мій $ сценарій, описаний вище, не буде працювати. Моє запитання було про те, чому працює $, але angular.element не має - хоча повна версія jQuery доступна.
додано Автор irascian, джерело
var target = document.getElementById('appBusyIndicator');

дорівнює

var target = $document[0].getElementById('appBusyIndicator');
21
додано
Краще використовувати другий приклад, щоб переконатись, що ваші залежності явні, і їх можна знущатися, чи не так?
додано Автор Luke, джерело

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

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

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

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

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

17
додано
Ти абсолютно правий. У 90% випадків, коли я думав, що потрібно вручну керувати DOM, я завершив рефакторинг коду, щоб видалити необхідність, і в кінці коду набагато чистіше.
додано Автор Stephen Chung, джерело

Ви можете отримати доступ до елементів за допомогою $ 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');
13
додано
find() - обмежується пошуком за назвою тегу
додано Автор RJV, джерело
angular.element (document) .find ('. someClass'); робота прекрасно чудово.
додано Автор Nishant Baranwal, джерело

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

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

$document[0].getElementById('id')
12
додано
Чому тут кутовий ін'єкційний масив?
додано Автор Peter, джерело

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

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

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

9
додано
Ви також можете просто переглянути вікно.document безпосередньо, замість того, щоб використовувати накладні витрати на послуги Angulars $ document.
додано Автор MatBee, джерело
Звичайно, ви можете, якщо ви не турбуєтесь про знущання $ document у вашому unittest
додано Автор Adamy, джерело
@realnot ви можете отримати доступ до об'єкта документів HTML DOM з будь-якого місця у своєму javascript. w3schools.com/jsref/dom_obj_document.asp
додано Автор Adamy, джерело
Мені зрозуміло: я отримую це warnig: Ви повинні використовувати службу $ document, а не об'єкт документа за замовчуванням, але що це означає? Будь-які документи про це? Дякую!
додано Автор realnot, джерело

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

angular.forEach(element.find('div'), function(node)
{
  if(node.id == 'someid'){
    //do something
  }
  if(node.className == 'someclass'){
    //do something
  }
});
6
додано
Будь ласка, не робіть цього. Використовуйте один з інших прикладів. Для цього не використовується жодна оптимізація пошуку хеш-таблиць.
додано Автор MatBee, джерело
елемент невизначений? Angular.element.find - це не функція, якою я намагаюсь випробувати себе без JQuery.
додано Автор landed, джерело

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

var target = angular.element(appBusyIndicator);

Зверніть увагу, що немає appBusyIndicator , це просто значення ідентифікатора.

Що відбувається за сценою: (припускаючи, що він застосовується до розділу) (взято з лінії anglecal.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 об'єкт повертається.

3
додано
може, у вас є jQuery на вашій сторінці?
додано Автор Vishal Anand, джерело
Я спробував це прямо зараз за допомогою Angular 1.5.8. Простий ідентифікатор повертає порожній результат. angular.element ("# myId") працює добре.
додано Автор Gosha U., джерело

Покращення відповіді кайзера:

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

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

3
додано
На завершення не повинно бути додаткової дужки ...
додано Автор shashanka n, джерело
Як згадується в кутовій документації для element.find : find() - Обмежений для пошуку за назвою тегів , він не працює на ідентифікаторах. Також у вас є додатковий закриття ) .
додано Автор paaat, джерело