HTML öğesi olmadan AngularJS ng-tekrar


91

Şu anda bir liste oluşturmak için bu kod parçasını kullanıyorum:

<ul ng-cloak>
    <div ng-repeat="n in list">
        <li><a href="{{ n[1] }}">{{ n[0] }}</a></li>
        <li class="divider"></i>
    </div>
    <li>Additional item</li> 
</ul>

Ancak, <div>öğe bazı tarayıcılarda çok küçük bazı oluşturma hatalarına neden oluyor. Ng-tekrarını div konteyneri olmadan yapmanın bir yolu veya aynı etkiyi elde etmek için alternatif bir yöntem olup olmadığını bilmek istiyorum.


Hangi işleme sorunlarından bahsediyorsunuz?
Ja͢ck

son li bölücü, istiflenmiş (chrome win7) gibi biraz daha kalın görünüyor. Bu bir css sorunu olabilir, ancak bunun açısal olarak düzeltilip düzeltilemeyeceğini bilmek istiyorum. Karşılaştırma için, knockoutJS, <! - -> kullanarak kapsayıcı içermeyen bağlamalara izin verir.
nehz

Görüyorum ki, sunucu tarafında phptal kullanıyorum ve özellikle bu amaç için bir tal: block etiketi var :) DOM ile her zaman açısal için daha zor olan yeni bir tür etiketi kabul etmeyeceğini tahmin
ediyorum

Yönergeyi nasıl kullandığınızı yansıtmak için html'yi de güncelleyebilir misiniz htmlAppend?
Nick

Bitti ... bunu bir süre önce yaptım ama işe yaradığını hatırlıyorum
nehz

Yanıtlar:


104

Andy Joslin'in söylediği gibi, ng-yinelemelere dayalı yorum üzerinde çalıştıklarını, ancak görünüşe göre çok fazla tarayıcı sorunu vardı . Neyse ki AngularJS 1.2, yeni direktifler ng-repeat-startve ile alt öğeler eklemeden yineleme için yerleşik destek ekler ng-repeat-end.

İşte Bootstrap sayfalandırması eklemek için küçük bir örnek :

<ul class="pagination">
  <li>
    <a href="#">&laquo;</a>
  </li>
  <li ng-repeat-start="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
  <li ng-repeat-end class="divider"></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

Tam bir çalışma örneği burada bulunabilir .

John Lindquist'in mükemmel egghead.io sayfasında bununla ilgili bir eğitim videosu da var .


3
Bu bir element baskısı gerektirmiyor mu?
hitautodestruct

2
Bunun basitçe <li ng-tekrar = "[1,2,3,4,5,6]"> <a href="#"> {{page}} </ a sayfasındaki sayfada neyi başardığını ciddi şekilde karıştırdım > </li> -düzenle: boş ver anladığımı düşünüyorum
Shadaez

6
Sadece göstermeye çalıştığınızı anlıyorum ng-repeat-start/endama bu kafa karıştırıcı bir örnek ve bunun için yanlış kullanım durumu. ng-repeatKodunuz liher öğe için fazladan bir boşluk oluşturduğundan burada bir standart kullanılmalıdır . Muhtemelen yazınızda bundan bahsetmelisiniz.
GFoley83

2
@ GFoley83 doğru. Ama her yineleme için bu ekstra öğeyi istiyor gibi görünüyor, bu olmadan mümkün olmayan bir şey ng-repeat-start. dividerDaha net olması için html sınıfını cevabıma ekleyeceğim .
jmagnusson

1
ng-repeat-startve ng-repeat-endbiraz kafa karıştırıcı. Angular belgeleri yardımcı olur: https://docs.angularjs.org/api/ng/directive/ngRepeat#special-repeat-start-and-end-points
perilandmishap

30

KnockoutJS kapsayıcısız bağlama sözdizimi

Lütfen bir saniye bekleyin: KnockoutJS foreach, foreachbağlayıcı dokümantasyonun Not 4'te tartışıldığı gibi , bağlayıcılığı için kapsayıcı olmayan bir ciltleme sözdizimi kullanmak için son derece uygun bir seçenek sunar . http://knockoutjs.com/documentation/foreach-binding.html

Altını Gizleme belgesi örneğinde gösterildiği gibi, bağlamanızı KnockoutJS'de şu şekilde yazabilirsiniz:

<ul>
    <li class="header">Header item</li>
    <!-- ko foreach: myItems -->
        <li>Item <span data-bind="text: $data"></span></li>
    <!-- /ko -->
</ul>

AngularJS bu tür bir sözdizimi sunmamanın oldukça talihsiz olduğunu düşünüyorum.


Angular ng-repeat-startveng-repeat-end

AngularJS ng-repeatproblem çözme yönteminde, karşılaştığım örnekler jmagnusson (yardımcı) cevabında yayınlanan türdendir.

<li ng-repeat-start="page in [1,2,3,4,5]"><a href="#">{{page}}</a></li>
<li ng-repeat-end></li>

Bu sözdizimini gördükten sonra ilk düşüncem: gerçekten mi? Neden Angular, hiçbir şey yapmak istemediğim ve Knockout'ta bu kadar kolay olan tüm bu ekstra işaretlemeyi zorluyor? Ama sonra hitautodestruct'un jmagnusson'ın cevabındaki yorumu beni meraklandırmaya başladı: ayrı etiketlerde ng-tekrar-başlangıç ​​ve ng-tekrar-bitiş ile ne üretiliyor?


Kullanmanın daha temiz bir yolu ng-repeat-startveng-repeat-end

Hitautodestruct iddiasının araştırılması üzerine, ng-repeat-endayrı bir etikete eklemek kesinlikle yapmayacağım şeydi de tamamen usesless elemanları üretir, çünkü çoğu durumda yapmak istiyorum: bu durumda, <li>onlara hiçbir şey öğeleri. Bootstrap 3'ün sayfalandırılmış listesi, liste öğelerini, gereksiz öğeler oluşturmamışsınız gibi görünecek şekilde biçimlendirir, ancak oluşturulan html'yi incelediğinizde, bunlar oradadır.

Neyse : Eğer temiz bir çözüm ve html daha kısa bir miktarda olması çok fazla bir şey gerekmez , sadece koymak ng-repeat-endvardır aynı html etiketi deklarasyonung-repeat-start .

<ul class="pagination">
  <li>
    <a href="#">&laquo;</a>
  </li>    
  <li ng-repeat-start="page in [1,2,3,4,5]" ng-repeat-end><a href="#"></a></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

Bu 3 avantaj sağlar:

  1. yazmak için daha az html etiketi
  2. işe yaramaz, boş etiketler Angular tarafından oluşturulmaz
  3. Yinelenecek dizi boş olduğunda, etiketi ng-repeatoluşturulmaz ve size Knockout'un kapsayıcı içermeyen bağlamasının bu konuda sağladığı aynı avantajı sağlar

Ama hala daha temiz bir yol var

Ve eksen, bu konuda github yorumların inceledikten sonra https://github.com/angular/angular.js/issues/1891 ,
kullanmak gerekmez ng-repeat-startve ng-repeat-endaynı avantajları elde etmek. Bunun yerine, jmagnusson örneğini tekrar çatallayarak, şöyle gidebiliriz:

<ul class="pagination">
  <li>
    <a href="#">&laquo;</a>
  </li>
  <li ng-repeat="page in [1,2,3,4,5,6]"><a href="#">{{page}}</a></li>
  <li>
    <a href="#">&raquo;</a>
  </li>
</ul>

Peki ne zaman kullanılmalı ng-repeat-startve ng-repeat-end? Uyarınca açısal belgeleri için

... tek bir ana öğe yerine bir dizi öğeyi tekrarlayın ...

Bu kadar konuşma yeter, bazı örnekler gösterin!

Yeterince adil; bu jsbin, bunu yaptığınızda ve kullanmadığınızda ne olduğunang-repeat-end , aynı etiketi .

http://jsbin.com/eXaPibI/1/


11
Görünüşe göre sorunun amacını yanlış anlamışsınız. Amaç, iki veya daha fazla liste öğesini aynı anda tekrar etmektir ve ne örneğiniz ne de bağladığınız sayfa bunu gerçekleştirmenin bir yolunu sağlamaktır. Eğer takılarak, kendini Bilindiği gibi ng-repeat-startve ng-repeat-endaynı elemana Eğer açısal en varsayılan ne zaman kullanabileceğini tamamen işe yaramaz ng-repeatve onunla yapılabilir.
Asad Saeeduddin

@ Esad - "sorunun amacı" OP tarafından açıkça belirtilmemiştir. Ayrıca, kabul edilen cevabın oluşturulmuş DOM çıktısını incelediniz mi? Hiç kimsenin bu tür bir çıktı istediğini hayal edemiyorum, en azından kesinlikle bir önyükleme sayfalama listesi için değil.
mg1075

1
@ mg1075 Evet, kabul edilen cevabın çıktısı kabul edilemez, bu yüzden buraya sonuna kadar kaydırdım. Sorunun amacı çok açık: HTML'deki yapıyı ortadan kaldıran ng-repeatOP'nin kullanımına bir alternatif bulmanın veya uygulamanın bir yolunu bulun . Sorudaki iki öğe için kullanmanın bir yolu olmadığı için cevabınız bunu yapmaz . Burada yanılıyorsam, lütfen OP'nin kodunu öğeyi ortadan kaldıracak şekilde uyarlayan örnek işaretleme sağlayın . ng-repeatdivlidiv
Asad Saeeduddin

@ Esad - OP, amaçladığı çıktının bitmiş bir örneğini sunsaydı, sorunun noktası daha net olurdu. Kabul edilen yanıtın temelde uygunsuz işaretlemeyle önyükleme sayfalandırması kullandığı "kabul edildi" yanıtı kabul etmesi, sorunu daha da karmaşık hale getirdi. Jsbin'deki Örnek 2, eğer gerçekten amaçlanan buysa, OP'nin problemini kabul edilen cevabın yaptığı gibi çözer, ancak hiç kimse önyükleme sayfalaması için bu tür işaretlemeyi kullanmamalıdır. jsbin.com/eXaPibI/1
mg1075

1
Aslında, ilk yanıta tekrar baktım ve oluşturulan işaretleme, gereksinimlerimi karşılamasa da, OP'nin kullanım durumu için tam olarak doğru. OP , jsbin'inizde gördüğünüz lifazladan bir bölücü öğenin oluşturulmasını liister.
Asad Saeeduddin

6

ngRepeat yeterli olmayabilir, ancak bunu özel bir yönerge ile birleştirebilirsiniz. Biraz jQuery'ye aldırmazsanız, koda bölücü öğeler ekleme görevini devredebilirsiniz.

 <li ng-repeat="item in coll" so-add-divide="your exp here"></li>

Böylesine basit bir yönerge gerçekten bir öznitelik değerine ihtiyaç duymaz, ancak size endekse, uzunluğa vb. Göre bir bölücü koşullu olarak eklemek veya tamamen farklı bir şey gibi birçok olasılık verebilir.


2
cool Özel bir yönerge ekledim ve işe yarıyor. Bu video kılavuzu yardımcı oldu: youtube.com/watch?v=A6wq16Ow5Ec
nehz

3

Son zamanlarda aynı sorunu yaşadım, çünkü rasgele bir aralık ve resim koleksiyonunu tekrarlamak zorunda kaldım - etraflarında bir öğe olması bir seçenek değildi - basit bir çözüm var, ancak "boş" bir yönerge oluşturun:

app.directive("diNull", function() {
        return {
            restrict: "E",
            replace: true,
            template: ""
        };
    });

Daha sonra bu Öğe üzerinde bir yineleme kullanabilirsiniz; burada element.url, o öğe için şablona işaret eder:

<di-null ng-repeat="element in elements" ng-include="element.url" ></di-null>

Bu, herhangi bir sayıda farklı şablonu etraflarında kapsayıcı olmadan tekrarlayacaktır.

Not: hmm, bunun işleme sırasında boş öğeyi kaldırdığına dair yemin edebilirdim, ancak tekrar kontrol etmek ... yine de düzen sorunlarımı çözmedi ... meraklı ve meraklı ...


replace2.0'dan beri kullanımdan kaldırılmıştır.
demalexx

Yukarıdakini denedim, ancak şablon: "" hiçbir şeyin değişmemesine neden oluyor. Bağlayıcıyı jsfiddle.net/markcoleman/fMP9s / 1'den kullandım ve değiştirdim: link: function (kapsam, öğe, attrs) {element [0] .outerHTML = ''; $ derleme (element.contents ()) (kapsam); }
Lauri Lubi

1

Yorum yönergesi kısıtlaması vardır, ancak ngRepeat bunu desteklemez (çünkü tekrarlanması için bir öğeye ihtiyaç duyar).

Sanırım açısal ekibin yorum tekrarları üzerinde çalışacaklarını söylediğini gördüm, ama emin değilim. Depoda bunun için bir sayı açmalısınız. http://github.com/angular/angular.js


2012 yorumu. Durum hala böyle mi? Belgelerinde arama yapmaya çalıştı ve herhangi bir referans bulamadı.
Zack S

1

Bunu yapmanın Angular sihirli bir yolu yoktur, sizin durumunuz için, Bootstrap kullanıyorsanız, geçerli HTML almak için bunu yapabilirsiniz. Daha sonra li.divider ekleyerek aynı etkiyi elde edeceksiniz.

Bir sınıf oluşturun:

span.divider {
 display: block;
}

Şimdi kodunuzu şununla değiştirin:

<ul ng-cloak>
 <li div ng-repeat="n in list">
    <a href="{{ n[1] }}">{{ n[0] }}</a>
    <span class="divider"></span>
 </li>
 <li>Additional item</li>
</ul>

1

gerçekten işe yarayan bir çözüm için

html

<remove  ng-repeat-start="itemGroup in Groups" ></remove>
   html stuff in here including inner repeating loops if you want
<remove  ng-repeat-end></remove>

bir angular.js yönergesi ekleyin

//remove directive
(function(){
    var remove = function(){

        return {    
            restrict: "E",
            replace: true,
            link: function(scope, element, attrs, controller){
                element.replaceWith('<!--removed element-->');
            }
        };

    };
    var module = angular.module("app" );
    module.directive('remove', [remove]);
}());

kısa bir açıklama için,

ng-tekrar kendini <remove> olması gerektiği gibi öğeye ve döngülere ve ng-tekrar-başlangıç ​​/ ng-tekrar-bitiş kullandığımız için, sadece bir eleman değil, bir html bloğu da döngüler oluşturur.

daha sonra özel kaldırma yönergesi <remove>başlangıç ​​ve bitiş öğelerini<!--removed element-->


Bu ilginç. Bununla birlikte, benim testimde replaceWith(...)bir yorum değil bir metin düğümü ile sonuçlanıyor. Sadece element.remove()eserler kullanarak buldum .
artfulrobot
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.