web-dev-qa-db-ja.com

html要素のないAngularJS ng-repeat

現在、このコードを使用してリストをレンダリングしています。

<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>

ただし、<div>要素は、一部のブラウザーで非常に小さなレンダリング障害を引き起こしています。 divコンテナなしでng-repeatを実行する方法、または同じ効果を達成するための代替方法があることを知りたいです。

90
nehz

Andy Joslinがコメントベースのng-repeatsに取り組んでいると言ったように しかし明らかにブラウザの問題が多すぎた 。幸いなことに、AngularJS 1.2は、新しいディレクティブng-repeat-startおよびng-repeat-endを使用して、子要素を追加せずに繰り返しの組み込みサポートを追加します。

以下に Bootstrap pagination を追加する小さな例を示します。

<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>

完全な動作例は here にあります。

John Lindquistには これに関する彼のすばらしいegghead.ioページでのビデオチュートリアル もあります。

103
jmagnusson

KnockoutJSコンテナーレスバインディング構文

ちょっと待ってください。KnockoutJSは、foreachバインディングドキュメントの注4で説明されているように、foreachバインディングにコンテナレスバインディング構文を使用するという非常に便利なオプションを提供します。 http://knockoutjs.com/documentation/foreach-binding.html

Knockoutドキュメントの例が示すように、次のようにKnockoutJSでバインディングを作成できます。

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

残念ながら、AngularJSはこのタイプの構文を提供していません。


Angularのng-repeat-startおよびng-repeat-end

ng-repeat問題を解決するAngularJSの方法では、私が出くわしたサンプルは、彼の(役に立つ)回答で投稿されたjmagnussonタイプです。

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

この構文を見たときの私の最初の考えは次のとおりです。どうしてAngularが、私が何もしたくないこの余分なマークアップをすべて強制し、Knockoutの方がずっと簡単なのはなぜですか?しかし、jmagnussonの答えのautodestructのコメントをヒットすると、疑問に思い始めました:ng-repeat-startとng-repeat-endで別々のタグで何が生成されているのですか?


ng-repeat-startおよびng-repeat-endを使用するよりクリーンな方法

Hitautodestructのアサーションを調査すると、別のタグにng-repeat-endを追加することは、ほとんどの場合、notしたいことです。まったく役に立たない要素を生成します:この場合、<li>アイテムは何も含まれていませんBootstrap 3のページ分割されたリストは、余分なアイテムを生成していないように見えるようにリストアイテムをスタイルしますが、生成されたhtmlを検査すると、そこにあります。

幸いなことに、よりクリーンなソリューションとより短い量のhtmlを得るために多くをする必要はありません:ただ置くng-repeat-endを持つ同じhtmlタグのng-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>

これには3つの利点があります。

  1. 書き込むHTMLタグが少ない
  2. 役に立たない空のタグはAngularによって生成されません
  3. 繰り返す配列が空の場合、ng-repeatのタグは生成されないため、Knockoutのコンテナーレスバインディングはこの点で同じ利点をもたらします。

しかし、まだきれいな方法があります

この問題に関するAngularのgithubのコメントをさらに確認した後、 https://github.com/angular/angular.js/issues/1891
同じ利点を得るために、ng-repeat-startng-repeat-endを使用する必要はありません。代わりに、jmagnussonの例を再度フォークして、次のようにします。

<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>

では、いつng-repeat-startng-repeat-endを使用するのでしょうか? angular documentation に従って、

... 1つの親要素ではなく、一連の要素を繰り返します...

十分な話、いくつかの例を示してください!

けっこうだ;このjsbinは、同じタグでng-repeat-endを使用した場合と使用しない場合に何が起こるかを5つの例で説明します。

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

30
mg1075

ngRepeatでは不十分な場合がありますが、カスタムディレクティブと組み合わせることができます。 jQueryを少し気にしないのであれば、コードに仕切り項目を追加するタスクを委任できます。

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

このような単純なディレクティブは、実際には属性値を必要としませんが、インデックス、長さ、または完全に異なるものに応じて条件付きでディバイダーを追加するなど、多くの可能性を提供します。

6
orcun

私は最近、スパンと画像の任意のコレクションを繰り返す必要があるという同じ問題を抱えていました-それらの周りの要素を持つことはオプションではありません-しかし、「null」ディレクティブを作成する簡単な解決策があります:

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

次に、その要素に対して繰り返しを使用できます。element.urlは、その要素のテンプレートを指します。

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

これにより、コンテナのない任意の数の異なるテンプレートが繰り返されます

注:うーん、これはレンダリング時にdi-null要素を削除することを盲目的に宣誓できたかもしれませんが、それをもう一度確認しても...レイアウトの問題はまだ解決しません...キュリオサーとキュリオサー...

3

コメントディレクティブには制限がありますが、ngRepeatはそれをサポートしていません(繰り返すには要素が必要なため)。

angularチームがコメントng-repeatsに取り組むと言ったのを見たと思いますが、わかりません。リポジトリで問題を開く必要があります。 http://github.com/angular/angular.js

1
Andrew Joslin

ブートストラップを使用している場合、有効なHTMLを取得するためにこれを行うことができるAngular魔法の方法はありません。次に、li.dividerを追加するのと同じ効果が得られます

クラスを作成します。

span.divider {
 display: block;
}

コードを次のように変更します。

<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>
0

本当に機能するソリューションのために

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>

angular.jsディレクティブを追加します

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

簡単な説明については、

ng-repeatは<remove>要素に自身をバインドし、必要に応じてループします。ng-repeat-start/ ng-repeat-endを使用したため、要素だけでなくhtmlのブロックをループします。

次に、カスタム削除ディレクティブは、<remove> startおよびfinish要素を<!--removed element-->で配置します

0
Clint