web-dev-qa-db-fra.com

angular.element vs document.getElementById ou le sélecteur jQuery avec contrôle de rotation (occupé)

J'utilise la version "angularisée" du contrôle Spin, comme documenté ici: http://blog.xvitcoder.com/adding-a-weel-progress-indicator-to-your-angularjs-application/

Une des choses que je n’aime pas dans la solution présentée est l’utilisation de jQuery dans le service qui attache efficacement le contrôle de rotation à l’élément DOM. Je préférerais utiliser les constructions angular pour accéder à l'élément. J'aimerais également éviter de "coder en dur" l'identifiant de l'élément que le spinner doit attacher dans le service et utiliser plutôt une directive qui définit l'identifiant dans le service (singleton) de sorte que les autres utilisateurs du service ou le service lui-même n'a pas besoin de le savoir.

Je suis aux prises avec ce que angular.element nous donne par rapport à quel document.getElementById sur le même élément id nous le donne. par exemple. Cela marche:

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

Aucun de ceux-ci ne:

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

Je fais clairement quelque chose qui devrait être assez évident faux! Quelqu'un peut-il aider?

En supposant que je puisse obtenir ce qui précède fonctionne, je rencontre un problème similaire lorsque je tente de remplacer l’accès jQuery à l’élément: par exemple, $(target).fadeIn('fast'); fonctionne angular.element('#appBusyIndicator').fadeIn('fast') ou angular.element('appBusyIndicator').fadeIn('fast') ne fonctionne pas.

Quelqu'un peut-il m'indiquer un bon exemple de documentation qui clarifie l'utilisation d'un élément Angular par rapport à l'élément DOM? Angular "encapsule" évidemment l'élément avec ses propres propriétés, méthodes, etc., mais il est souvent difficile d'obtenir la valeur d'origine. Par exemple, si j'ai un champ <input type='number'> et que je veux accéder au contenu d'origine visible dans l'interface utilisateur lorsque l'utilisateur tape "-" (sans les guillemets), rien ne me vient, probablement parce que "type = number "signifie que Angular rejette l'entrée même si elle est visible dans l'interface utilisateur et que je souhaite la voir afin que je puisse la tester et la supprimer.

Tous les pointeurs/réponses appréciés.

Merci.

153
irascian

Cela peut ​​fonctionner comme ça:

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

Vous intégrez l'appel Document.querySelector() _ Javascript Javascript dans l'appel angular.element(). Ainsi, vous obtenez toujours l'élément dans un objet jqLite ou jQuery, selon que jQuery soit disponible ou chargé.

Documentation officielle pour angular.element:

Si jQuery est disponible, angular.element est un alias de la fonction jQuery. Si jQuery n'est pas disponible, angular.element délègue à Angular le sous-ensemble intégré de jQuery, appelé "jQuery lite" ou jqLite .

Toutes les références d'élément dans Angular sont toujours entourées de jQuery ou jqLite (comme l'argument d'élément dans une directive compile ou link une fonction). Ils ne sont jamais bruts DOM références.

Si vous vous demandez pourquoi utiliser document.querySelector(), veuillez lire cette réponse .

222
kaiser

Vous devriez lire le angular element docs si vous ne l'avez pas encore fait, afin de comprendre ce qui est supporté par jqLite et ce qui n'est pas -jqlite est un sous-ensemble de jQuery intégré à angular.

Ces sélecteurs ne fonctionneront pas avec jqLite uniquement, car les sélecteurs par id ne sont pas pris en charge.

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

Alors, soit:

  • vous utilisez jqLite seul, plus limité que jquery, mais suffisant dans la plupart des situations.
  • ou vous incluez l'intégralité de jQuery lib dans votre application et vous l'utilisez comme d'habitude jquery, aux endroits où vous avez vraiment besoin de jQuery.

Edit: Notez que jQuery doit être chargé avant angularJS afin de prendre le pas sur jqLite:

Real jQuery a toujours priorité sur jqLite, à condition qu'il ait été chargé avant l'événement DOMContentLoaded.

Edit2: J'ai raté la deuxième partie de la question avant:

Le problème avec <input type="number">, je pense ce n’est pas un problème de angular, c’est le comportement voulu de la élément numérique natif html5.

Il ne renverra pas de valeur non numérique, même si vous essayez de le récupérer avec .val() de jquery ou avec l'attribut raw .value.

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

est égal à

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

Je ne pense pas que ce soit la bonne façon d'utiliser angulaire. Si une méthode framework n'existe pas, ne la créez pas! Cela signifie que le cadre (ici angulaire) ne fonctionne pas de cette façon.

Avec angular, vous ne devez pas manipuler DOM de cette manière (la méthode jQuery), mais utiliser angular helper tel que

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

Ou créez votre propre directive (votre propre composant DOM) afin d’avoir un contrôle total sur celle-ci.

En passant, vous pouvez voir ici http://caniuse.com/#search=queryselector querySelector est bien pris en charge et peut donc être utilisé en toute sécurité.

17
Thomas Decaux

Si quelqu'un utilise gulp, il affichera une erreur si nous utilisons document.getElementById() et suggère d'utiliser $document.getElementById() mais cela ne fonctionne pas.

Utilisation -

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

Vous pouvez accéder aux éléments en utilisant $ document ($ document doit être injecté)

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

ou avec l'élément angular, les éléments spécifiés sont accessibles en tant que:

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');
16
Nishant Baranwal

Vous devez injecter $ document dans votre contrôleur et l’utiliser à la place de l’objet document original.

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

Si vous n'avez pas besoin d'utiliser l'élément de style jquery wrap, $ document [0] .querySelector ('# MyID') vous donnera l'objet DOM.

10
Adamy

Cela a bien fonctionné pour moi.

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

Amélioration de la réponse de Kaiser:

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

N'oubliez pas d'injecter $document dans votre directive

3
Rob H

Peut-être que je suis trop tard ici, mais ça va marcher:

var target = angular.element(appBusyIndicator);

Remarquez qu'il n'y a pas de appBusyIndicator, il s'agit d'une valeur d'ID en clair.

Ce qui se passe dans les coulisses: (en supposant que cela s’applique à un div) (tiré de la ligne angular.js n °: 2769 et suivantes ...)

/////////////////////////////////////////////
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);
  }

Par défaut, s'il n'y a pas de requête jQuery sur la page, jqLite sera utilisé. L'argument est compris en interne comme un identifiant et l'objet jQuery correspondant est renvoyé.

3
Vishal Anand