spin (meşgul) kontrollü açısal.element vs document.getElementById veya jQuery seçici


157

Burada gösterildiği gibi Spin denetiminin "Açısallaştırılmış" sürümünü kullanıyorum: http://blog.xvitcoder.com/adding-a-weel-progress-indicator-to-your-angularjs-application/

Gösterilen çözüm hakkında sevmediğim şeylerden biri, jQuery'nin etkin bir şekilde döndürme denetimini DOM öğesine bağlayan hizmette kullanılmasıdır. Elemana erişmek için açısal yapılar kullanmayı tercih ederim. Ayrıca, döndürücünün hizmet içinde eklemesi gereken öğenin kimliğini "sabit kodlamadan" kaçınmak ve bunun yerine hizmetin diğer kullanıcılarını (singleton) kimliğini ayarlayan bir yönerge kullanmak veya hizmetin kendisi bunu bilmek gerekmez.

Ne açısal.element bize aynı element id bize ne document.getElementById verir ile mücadele ediyorum. Örneğin. Bu çalışıyor:

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

Bunların hiçbiri şunları yapmaz:

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

Açıkça yanlış olması gereken bir şey yapıyorum! Biri yardım edebilir mi?

Yukarıdaki çalışmayı alabilir varsayarak, öğeye jQuery erişimini değiştirmeye çalışırken benzer bir sorun var: örneğin $(target).fadeIn('fast'); çalışır angular.element('#appBusyIndicator').fadeIn('fast')ya angular.element('appBusyIndicator').fadeIn('fast')da değil

Birisi beni DOM öğesiyle bir Açısal "öğenin" kullanımını açıklayan belgelerin iyi bir örneğine işaret edebilir mi? Açısal, öğeyi kendi özellikleri, yöntemleri vb. İle "sarar" ancak orijinal değeri elde etmek genellikle zordur. Örneğin, bir <input type='number'>alanım varsa ve kullanıcı "-" (tırnak işaretleri olmadan) yazdığında kullanıcı arayüzünde görünen orijinal içeriğe erişmek istiyorsanız, muhtemelen "type = number", Angular reddediyor demektir giriş kullanıcı arayüzünde görünür olmasına rağmen ve bunu görmek istiyorum, böylece test edebilir ve temizleyebilirim.

Herhangi bir işaretçi / cevap takdir.

Teşekkürler.


5
angular.element, jQuery yüklüyorsanız bir jQlite nesnesi veya jQuery nesnesidir.
Neil

Yanıtlar:


226

Bu şekilde çalışabilir:

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

Sen sarmak Document.querySelector()yerli JavaScript içine çağrıyı angular.element()çağrı. Böylece , kullanılabilir / yüklü olup olmamasına bağlı olarak öğeyi her zaman bir jqLite veya jQuery nesnesinde alırsınızjQuery .

Resmi belgeler angular.element:

Eğer jQuery kullanılabilir, angular.elementbir başka adıdır jQueryişlevi. JQuery kullanılamıyorsa, "jQuery lite" veya jqLite adı verilen Angular ın yerleşik alt kümesine angular.elementdelege eder .jQuery

İçindeki tüm öğe referansları Angularher zaman jQuery veya jqLite(direktifler derleme veya link fonksiyonundaki element argümanı gibi) ile sarılır . Asla ham DOMreferans değildirler.

Neden kullanacağınızı merak ediyorsanız document.querySelector(), lütfen bu cevabı okuyun .


41
Herhangi bir neden, document.querySelector ('# ...') öğesini yalnızca document.getElementById () öğesini kullanmasını tercih etmek için herhangi bir neden var mı?
Kato

4
Bunu açısal bir öğe üzerinde de yapabilirsiniz: var elDivParent = angular.element (elem [0] .querySelector ('# an-id'));; elem bir açısal öğe. Bu şekilde bir elemanın içinde arama yapabilirsiniz. Birim testleri için kullanışlıdır.
unludo

4
@Kato Bu cevapta daha fazla bilgi . Umarım yardımcı olur.
kaiser

Google Maps API ile çalışan ve bu çalıştı: var autocomplete = new google.maps.places.Autocomplete( $document[0].querySelector('#address'), { types: ['geocode'], componentRestrictions: {country: 'us'} } );. @Kaiser için bahşiş için teşekkürler. Bazı nedenlerden dolayı, api haritaları ilk paramda geçirdiğim şeyin angular.element(document.querySelector('#address')), kullandığım zaman bir girdi olmadığı , ancak iyi biten her şeyin iyi olduğundan şikayet etti .
nymo

49

Henüz açmadıysanız açısal öğe belgelerini okumalısınız , böylece jqLite tarafından neyin desteklendiğini ve niçin -jqlite'nin açısal olarak oluşturulmuş bir jquery alt kümesi olduğunu anlayabilirsiniz.

Bu seçiciler çalışmaz , çünkü tek başına jqLite ile seçiciler id tarafından desteklenmemektedir.

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

Bu yüzden ya :

  • jqLite'ı yalnızca jquery'den daha sınırlı, ancak çoğu durumda yeterli kullanırsınız.
  • veya tam jQuery lib'i uygulamanıza ekleyebilir ve gerçekten jquery'ye ihtiyacınız olan yerlerde normal jquery gibi kullanabilirsiniz.

Düzenleme: jqLite öncelikli olması için jQuery angularJS önce yüklenmesi gerektiğini unutmayın:

DOMContentLoaded olayı başlatılmadan önce yüklenmesi koşuluyla, gerçek jQuery her zaman jqLite'den önceliklidir.

Edit2: Sorunun ikinci bölümünü daha önce kaçırdım:

İle sorunu <input type="number">, ben düşünüyorum o, o amaçlanan davranış bir açısal konudur değildir yerli html5 numarası elemanı.

Jquery .val()veya raw .valueözniteliği ile almaya çalışsanız bile sayısal olmayan bir değer döndürmez .


2
Tam jQuery kütüphanesine sahibiz - aksi takdirde yukarıda açıklanan benim $ senaryom işe yaramaz. Sorum tam jQuery kullanılabilir olsa bile $ neden çalışır ama angular.element işe yaramadı.
irascian

1
Angular.js'den önce veya sonra jQuery ekliyor musunuz? Açısaldan önce dahil edilmelidir . Kimliğe göre Seçiciler do : jQuery mevcut olan işi jsbin.com/ohumiy/1/edit
Garst

1
Başka bir yönergede çalışıyorlar (yani bir şeye kimliğe erişmek için açısal. Eleman). Aynı jQuery eşdeğerinin neden doğrudan çalışması gerektiğini anlamasam da, sorun bu öğenin kendisini bu öğeye ekleyerek çalıştığı gibi görünüyor. Doğrudan jQuery kullanmak benim yönerge bir kapanış etiketi olması gerekir - kendi kendine kapanış etiketi çalışmıyor (hata sadece boş bir ekran) bu beni kontrol şüpheli yapar.
irascian

2
2. noktamda, bir öğenin içeriğini almak için kullanılabilecek view $ değeri gibi bir şey de vardır, ancak giriş türü = kullanıcı "-" girişinin olduğu yerde bu boştur. Angular benim yönerge programlı erişimim olmasa bile "-" hala kullanıcı arayüzünde olduğundan Angular adım önce ÖNEMLİ içeriği görmek için öğe üzerinde $ rawInputValue gibi bir şey istiyorum.
irascian

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

eşittir

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

1
Bağımlılıklarınızın açık ve alay edilebilir olmasını sağlamak için ikinci örneği kullanmak daha iyidir, değil mi?
Luke

öyle olmalı, ama sanırım açısal 2 + 'da sadece daktilo özelliklerine güveniyoruz. Artık bu şeyler için endişelenmenize gerek yok :)
Dasun

17

Açısal kullanmanın doğru yolu olduğunu düşünmüyorum. Bir çerçeve yöntemi yoksa, oluşturmayın! Bu, çerçevenin (burada açısal) bu şekilde çalışmadığı anlamına gelir.

Açısal ile DOM'u bu şekilde değiştirmemelisiniz (jquery yolu), ancak

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

Ya da üzerinde tam denetime sahip olmak için kendi direktifinizi (kendi DOM bileşeniniz) oluşturun.

BTW, http://caniuse.com/#search=queryselector querySelector iyi desteklenmektedir ve bu nedenle güvenle kullanabilirsiniz.


2
Kesinlikle haklısın. El ile DOM manipüle gerektiğini düşündüğüm vakaların% 90 +, ihtiyacını kaldırmak için kodu refactoring sona erdi ve sonunda kod çok daha temiz.
Stephen Chung

17

Eğer yudum kullanan biri varsa, kullanırsak bir hata gösterir document.getElementById()ve kullanılmasını önerir, $document.getElementById()ancak işe yaramaz.

Kullan -

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

Açısal neden buraya bir dizi enjekte ediyor?
Peter

16

$ Document kullanarak öğelere erişebilirsiniz ($ document enjekte edilmelidir)

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

veya açısal eleman ile belirtilen elemanlara şu şekilde erişilebilir:

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 () - Etiket adına göre aramalarla sınırlıdır
RJV

angular.element (belge) .find (' birSınıf.); mükemmel çalışıyor.
Nishant Baranwal

10

Denetleyicinize $ document enjekte etmeli ve orijinal belge nesnesi yerine kullanmalısınız.

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

Jquery stil öğesi kaydırmasına ihtiyacınız yoksa, $ document [0] .querySelector ('# MyID') size DOM nesnesini verecektir.


1
Angulars $ belge hizmeti ek yükünü kullanmak yerine window.document öğesine doğrudan başvurabilirsiniz.
MatBee

5
Elbette, birim testinizde $ dokümanı alay etme konusunda endişelenmiyorsanız
Adamy

Benim için net değil: Bu uyarıyı alıyorum: Varsayılan belge nesnesi yerine $ document hizmetini kullanmalısınız, ama ne anlama geliyor? Bu konuda herhangi bir doküman var mı? Teşekkürler!
realnot

@realnot HTML DOM Belge Nesnesine javascript'inizin herhangi bir yerinden erişebilirsiniz. w3schools.com/jsref/dom_obj_document.asp
Adamy

6

Bu benim için iyi çalıştı.

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

3
eleman tanımsız mı? angular.element.find JQuery olmadan seninkini denemek benim için bir işlev değildir.
indi

3
Lütfen bunu yapma. Diğer örneklerden birini kullanın. Bu, hiç karma tablo arama optimizasyonu kullanmaz.
MatBee

4

Kaiser yanıtında iyileşme:

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

$documentDirektifinize enjekte etmeyi unutmayın


21
Element.find : için açısal dokümantasyonda belirtildiği gibi find() - Limited to lookups by tag name, kimlikler üzerinde çalışmaz. Ayrıca ekstra bir kapanış var ).
paaat

3

Belki burada çok geç kaldım ama bu işe yarayacak:

var target = angular.element(appBusyIndicator);

Dikkat, yok appBusyIndicator , düz kimlik değeridir.

Perde arkasında neler oluyor: (bir div'a uygulandığı varsayılarak) (angular.js satır no: 2769'dan alınmıştır ...)

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

Varsayılan olarak sayfada jQuery yoksa, jqLite kullanılır. Bağımsız değişken dahili olarak bir id olarak anlaşılır ve karşılık gelen jQuery nesnesi döndürülür.


Bunu şu anda Angular 1.5.8 ile denedim. Düz bir kimlik boş sonuç döndürür. angular.element("#myId")iyi çalışıyor.
Gosha

belki sayfanızda jQuery var?
Vishal Anand
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.