angular.element vs document.getElementById sau selector jQuery cu control de rotire (ocupat) (Programare, Jquery, Angularjs)

irascian a intrebat.
a intrebat.

Eu folosesc versiunea „angularizată” a controlului Spin, așa cum este documentată aici: http://blog.xvitcoder.com/adding-a-weel-progress-indicator-to-your-angularjs-application/

Unul dintre lucrurile care nu-mi plac la soluția prezentată este utilizarea jQuery în serviciul care atașează efectiv controlul Spin la elementul DOM. Aș prefera să folosesc construcțiile angular pentru a accesa elementul. De asemenea, aș dori să evit „hard-coding” id-ul elementului la care trebuie să se atașeze spinner-ul în cadrul serviciului și să folosesc în schimb o directivă care să stabilească id-ul în serviciu (singleton), astfel încât alți utilizatori ai serviciului sau serviciul însuși să nu fie nevoiți să știe acest lucru.

Mă lupt cu ceea ce ne oferă angular.element față de ceea ce ne oferă document.getElementById pe același id de element.ex. Acest lucru funcționează:

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

Niciuna dintre acestea nu funcționează:

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

E clar că fac ceva care ar trebui să fie destul de evident greșit! Poate cineva să mă ajute?

Presupunând că reușesc să fac să funcționeze cele de mai sus, am o problemă similară cu încercarea de a înlocui accesul jQuery la element:ex. $(target).fadeIn('fast'); funcționează angular.element('#appBusyIndicator').fadeIn('fast') sau angular.element('appBusyIndicator').fadeIn('fast') nu funcționează

Poate cineva să-mi indice un exemplu bun de documentație care să clarifice utilizarea unui „element” Angular față de elementul DOM? Evident, Angular „înfășoară” elementul cu propriile sale proprietăți, metode etc., dar este adesea dificil să obținem valoarea originală. De exemplu, dacă am un element <input type='number'> și vreau să accesez conținutul original care este vizibil în UI atunci când utilizatorul tastează „–” (fără ghilimele), nu obțin nimic, probabil pentru că „type=number” înseamnă că Angular respinge intrarea, chiar dacă este vizibilă în UI și vreau să o văd pentru a o testa și a o elimina.

Orice indicații/răspunsuri sunt apreciate.

Mulțumesc.

Comentarii

  • angular.element este un obiect jQlite sau un obiect jQuery dacă încărcați jQuery. –  > Por Neil.
10 răspunsuri
kaiser

Este poate funcționa așa:

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

Înfășurați Document.querySelector() Javascript nativ în apelul angular.element() apel. Astfel, veți obține întotdeauna elementul într-un jqLite sau jQuery în funcție de faptul că jQuery este disponibil/încărcat.

Documentația oficială pentru angular.element:

Dacă jQuery este disponibil, angular.element este un alias pentru jQuery funcție. Dacă jQuery nu este disponibil, angular.element deleagă la Angularîn subansamblul încorporat de jQuery, care se numește „jQuery lite” sau jqLite.

Toate referințele la elemente din Angular sunt întotdeauna înfășurate cu jQuery sau jqLite (cum ar fi argumentul elementului într-o funcție de compilare sau de legătură a directivelor). Ele nu sunt niciodată brute DOM referințe.

În cazul în care vă întrebați de ce să utilizați document.querySelector(), vă rugăm să citiți acest răspuns.

Comentarii

    41

  • Există vreun motiv pentru care cineva ar prefera document.querySelector(‘#…’) în loc să folosească pur și simplu document.getElementById()? –  > Por Kato.
  • Puteți face acest lucru și pe un element angular : var elDivParent = angular.element( elem[0].querySelector(‘#an-id’)));, elem fiind un element angular. În acest fel, puteți căuta în interiorul unui element. Util pentru testele unitare. –  > Por unludo.
  • @Kato Mai multe informații în acest răspuns. Sper că vă ajută. –  > Por kaiser.
  • lucrând cu Google Maps API, și acest lucru a funcționat: var autocomplete = new google.maps.places.Autocomplete( $document[0].querySelector('#address'), { types: ['geocode'], componentRestrictions: {country: 'us'} } );. Mulțumesc pentru pont @kaiser. Dintr-un motiv oarecare, API-ul de hărți s-a plâns că ceea ce am trecut în primul parametru nu a fost o intrare atunci când am folosit angular.element(document.querySelector('#address')), dar totul e bine când se termină cu bine. –  > Por nymo.
garst

Ar trebui să citiți manualul angular dacă nu ați făcut-o încă, pentru a înțelege ce este suportat de jqLite și ce nu -jqlite este un subset de jquery integrat în angular.

Acei selectori nu vor funcționa doar cu jqLite, deoarece selectori după id nu sunt acceptate.

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

Așadar, fie :

  • folosiți doar jqLite, mai limitat decât jquery, dar suficient în majoritatea situațiilor.
  • fie includeți biblioteca jQuery completă în aplicația dvs. și o utilizați ca jquery normal, în locurile în care aveți cu adevărat nevoie de jquery.

Editare: Rețineți că jQuery ar trebui să fie încărcat înainte de angularJS pentru a avea prioritate față de jqLite:

JQuery real are întotdeauna prioritate față de jqLite, cu condiția să fi fost încărcat înainte de declanșarea evenimentului DOMContentLoaded.

Editare2: Am omis a doua parte a întrebării de mai devreme:

Problema cu <input type="number"> , I cred că nu este o problemă de angular, este vorba de comportamentul intenționat al nativ html5.

Acesta nu va returna o valoare nenumerică chiar dacă încercați să o recuperați cu jquery’s .val() sau cu elementul brut .value atribut.

Comentarii

  • Avem biblioteca jQuery completă – altfel scenariul meu $ explicat mai sus nu ar funcționa. Întrebarea mea era în jurul motivului pentru care $ funcționează, dar angular.element nu – chiar dacă jQuery complet este disponibil. –  > Por irascian.
  • Includeți jQuery înainte sau după angular.js? Ar trebui să fie inclus înainte de angular. Selectori după id face funcționează cu jQuery disponibil: jsbin.com/ohumiy/1/edit –  > Por garst.
  • Ele funcționează într-o altă directivă (adică angular.element pentru a accesa ceva după id). Problema pare să fie modul în care funcționează acest control prin atașarea la acel element, deși nu înțeleg de ce ar trebui să funcționeze același echivalent jQuery direct. Folosind jQuery direct, directiva mea TREBUIE să aibă un tag de închidere – tagul de autoînchidere nu funcționează (nu există erori, doar un ecran alb), ceea ce mă face să suspectez controlul. –  > Por irascian.
  • Referitor la al 2-lea punct al meu există și ceva de genul view$value care poate fi folosit pentru a prelua conținutul unui element dar în cazul input type=number unde utilizatorul a introdus „–” acesta este gol. Vreau o proprietate ceva de genul $rawInputValue pe element pentru a vedea conținutul ÎNAINTE ca Angular să fi intervenit pentru că „–” este încă în UI chiar dacă nu am acces la el programatic în directiva mea. –  > Por irascian.
Dasun
var target = document.getElementById('appBusyIndicator');

este egal cu

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

Comentarii

  • Este mai bine să folosești al doilea exemplu pentru a te asigura că dependențele tale sunt explicite și pot fi simulate, nu? –  > Por Luke.
  • ar trebui să fie, dar cred că în angular 2+ ne bazăm mai mult pe caracteristicile typescript. Nu mai trebuie să ne facem griji cu privire la aceste lucruri 🙂 –  > Por Dasun.
Thomas Decaux

Nu cred că este modul corect de a folosi angular. Dacă o metodă de cadru nu există, nu o creați! Aceasta înseamnă că cadrul (aici angular) nu funcționează în acest fel.

Cu angular nu ar trebui să manipulați DOM în acest fel (modul jquery), ci să folosiți ajutoare angular cum ar fi

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

Sau creați-vă propria directivă (propria componentă DOM) pentru a avea control total asupra acesteia.

BTW, puteți vedea aici http://caniuse.com/#search=queryselector querySelector este bine susținut și poate fi utilizat în siguranță.

Comentarii

  • Aveți perfectă dreptate. În peste 90% din cazurile în care am crezut că trebuie să manipulez manual DOM, am ajuns să refactorizez codul pentru a elimina această necesitate și, în final, codul este mult mai curat. –  > Por Stephen Chung.
Kanchan

Dacă cineva folosește gulp, se afișează o eroare dacă folosim document.getElementById() și ne sugerează să folosim $document.getElementById() dar nu funcționează.

Utilizați –

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

Comentarii

  • De ce injectează angular o matrice aici? –  > Por Peter.
Nishant Baranwal

Puteți accesa elementele folosind $document ($document trebuie să fie injectat)

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

sau cu angular element, elementele specificate pot fi accesate ca:

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');

Comentarii

  • find() – Limitat la căutări după numele etichetei –  > Por RJV.
  • angular.element(document).find(‘.someClass’); funcționează perfect. –  > Por Nishant Baranwal.
Adamy

Ar trebui să injectați $document în controlerul dvs. și să îl utilizați în locul obiectului document original.

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

Dacă nu aveți nevoie de înfășurarea elementului în stil jquery, $document[0].querySelector(‘#MyID’) vă va oferi obiectul DOM.

Comentarii

  • Puteți la fel de bine să faceți trimitere directă la window.document în loc să folosiți serviciul $document de la Angulars. –  > Por MatBee.
  • Bineînțeles că puteți dacă nu vă faceți griji cu privire la mocking $document în unittest-ul dvs.  > Por Adamy.
  • Nu este clar pentru mine: Primesc acest warnig: Ar trebui să utilizați serviciul $document în loc de obiectul document implicit, dar ce înseamnă? Există documente despre asta? Mulțumesc! –  > Por realnot.
  • @realnot puteți accesa obiectul document HTML DOM de oriunde în javascript. w3schools.com/jsref/dom_obj_document.asp –  > Por Adamy.
susrut316

Acest lucru a funcționat pentru mine bine.

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

Comentarii

  • elementul este nedefinit ? angular.element.find nu este o funcție pentru mine încercând a ta fără JQuery. –  > Por a aterizat.
  • Vă rugăm să nu faceți acest lucru. Folosiți unul dintre celelalte exemple. Acesta nu folosește deloc optimizări de căutare a tabelei hash. –  > Por MatBee.
Rob H

Îmbunătățire la răspunsul lui kaiser:

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

Nu uitați să injectați $document în directiva dvs.

Comentarii

    21

  • După cum se menționează în documentația angular pentru element.find: find() - Limited to lookups by tag name, acesta nu funcționează pe id-uri. De asemenea, aveți o închidere suplimentară ). –  > Por paaat.
Vishal Anand

Poate că am ajuns prea târziu aici, dar acest lucru va funcționa:

var target = angular.element(appBusyIndicator);

Notă, nu există nici o appBusyIndicator, este o valoare ID simplă.

Ce se întâmplă în spatele scenei: (presupunând că este aplicat pe un div) (preluat din angular.js linia nr : 2769 și următoarele…)

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

În mod implicit, dacă nu există jQuery pe pagină, va fi utilizat jqLite. Argumentul este înțeles la nivel intern ca un id și este returnat obiectul jQuery corespunzător.

Comentarii

  • Am încercat acest lucru chiar acum cu Angular 1.5.8. Un ID simplu returnează un rezultat gol. angular.element("#myId") funcționează bine. –  > Por Gosha U..
  • poate ai jQuery pe pagina ta? –  > Por Vishal Anand.