HTML要素のないAngularJS ng-repeat


91

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

<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を実行する方法、または同じ効果を達成するためのいくつかの代替方法があることを知りたいです。


どのようなレンダリングの問題について話しているのですか?
ジャック

最後のliディバイダーは、積み重ねられた(クロムwin7)のように少し厚いようです。これはcssの問題である可能性がありますが、角度で修正できるかどうかを知りたいです。比較のために、knockoutJSは<!-->を使用してコンテナーなしのバインディングを許可します。
nehz

私は、サーバー側でPHPTALを使うと、彼らはTALを持って、次を参照してください。ブロックタグ特にこの目的のために:) DOMは常に難しい角度でのタグの新しい種類を受け付けないとの推測
ジャック・

また、htmlAppendディレクティブの使用方法を反映するようにHTMLを更新できますか?
Nick

完了...このaがしばらく前にやったが、私はそれが働いて覚えていますか
nehz

回答:


104

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

Bootstrapのページネーションを追加するための小さな例を次に示します。

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

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

ジョンリンドキストの優れたegghead.ioページに、このビデオチュートリアルがあります


3
これは要素の印刷を必要としませんか?
hitautodestruct 2013年

2
単純に<li ng-repeat = "page in [1,2,3,4,5,6]"> <a href="#"> {{page}} </ aでこれが何を達成するのか、私はひどく混乱しています。 > </ LI> -edit:用事私はそれを得ると思います
Shadaez

6
デモンストレーションをしようとしているだけだと思いますng-repeat-start/endが、これは紛らわしい例であり、間違った使用例です。ng-repeatコードではli各項目に余分な空をレンダリングするため、ここでは標準を使用する必要があります。あなたはおそらくあなたの投稿でそれを言及する必要があります。
GFoley83 2014

2
@ GFoley83正解です。しかし、彼はイテレーションごとにその追加の要素を望んでいるようですng-repeat-startdividerより明確にするために、答えにhtmlクラスを追加します。
jmagnusson 2014

1
ng-repeat-startng-repeat-end少し混乱しています。Angularのドキュメントが役立ちます:https
//docs.angularjs.org/api/ng/directive/ngRepeat#special-repeat-start-and-end-points

30

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

しばらくお待ちください。KnockoutJSにforeachは、foreachバインディングドキュメントの注4で説明されているように、バインディングにコンテナレスバインディング構文を使用するという非常に便利なオプションが用意されています。 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-startng-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の答えにあるhitautodestructのコメントに疑問が生じ始めました。別のタグでng-repeat-startとng-repeat-endで何が生成されているのでしょうか。


よりクリーンな使用方法ng-repeat-startng-repeat-end

hitautodestructの主張の調査の結果、追加ng-repeat-end別のタグににすると、私は考えまさにあるではない、それは全くusesless要素を生成しているため、ほとんどのケースでやりたい。この場合は、<li>その中の何ものアイテム。Bootstrap 3のページ付けされたリストはリストアイテムのスタイルを設定しているため、余分なアイテムを生成していないように見えますが、生成されたhtmlを検査すると、そこにあります。

幸いなことに、よりクリーンなソリューションとより短い量のhtmlを作成するために多くのことを行う必要はありません。宣言をと同じhtmlタグに置くだけng-repeat-endng-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のコンテナーレスバインディングと同じ利点が得られます。

しかし、まだよりクリーンな方法があります

角度のために、この問題にgithubののコメントを検討し、さらに後、https://github.com/angular/angular.js/issues/1891
あなたが使用する必要はありませんng-repeat-startし、ng-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?あたりとして、角度のドキュメント

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

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

けっこうだ; このjsbinはng-repeat-end、同じタグで使用した場合と使用しない場合の結果の5つの例を示します。

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


11
あなたはその質問の意味を誤解しているようです。目標は、2つ以上のリストアイテムを同時に繰り返すことであり、これを実現する方法を提供するために、例やリンクしたページはありません。あなた自身を述べてきたように、取り付けng-repeat-startおよびng-repeat-endあなたが角度のデフォルトを使用することができたときに、同じ要素には全く役に立たないですng-repeatし、それを使って行うこと。
Asad Saeeduddin 2014

@アサド-OPは「質問のポイント」を明確に述べていません。また、受け入れられた回答のレンダリングされたDOM出力を検査しましたか?私はそのような出力を望んでいる誰も想像できません、少なくとも確かにブートストラップページネーションリストのために。
mg1075 14

1
@ mg1075はい、受け入れられた回答の出力は受け入れられないため、ここまでスクロールしました。質問の要点は非常に明確ですng-repeat。OPの使用方法に代わる方法を見つけたり、HTMLのアーティファクトng-repeatを除去したりする方法を見つけてdivください。li質問の2つの要素にそれを使用する方法がないため、あなたの答えはこれを行いません。ここで間違っている場合は、OPのコードを適合させてdiv要素を削除するサンプルマークアップを提供してください。
Asad Saeeduddin 2014

@アサド-OPが意図したアウトプットの完成した例を提供した場合、質問のポイントはより明確になったでしょう。彼が「受け入れられた」回答を受け入れたという事実は、受け入れられた回答が本質的に不適切なマークアップによるブートストラップページネーションを使用する場合、問題をさらに混乱させました。jsbinの例2は、それが本当に意図されているものである場合、受け入れられた回答が行う方法でOPの問題を解決しますが、ブートストラップのページネーションにそのタイプのマークアップを使用するべきではありません。jsbin.com/eXaPibI/1
mg1075

1
実際、最初の答えをもう一度見ただけで、生成されたマークアップは、要件を満たしていなくても、OPのユースケースにぴったりです。OPは、jsbinに表示されるli追加のディバイダーアイテムの生成を望んliでいます。
Asad Saeeduddin 2014

6

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

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

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


2
私はカスタムディレクティブを追加し、それが動作します。この動画ガイドが
役に立ち

3

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

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

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

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

これは、周囲にコンテナがない、任意の数の異なるテンプレートを繰り返します。

注:うーん、私はこれをレンダリングするときにdi-null要素を削除することを宣言できたかもしれませんが、もう一度それをチェックすると...それでも私のレイアウトの問題は解決しました... curioserとcurioser ...


replace2.0から非推奨になりました。
demalexx 2014年

上記を試しましたが、テンプレート: ""を指定すると何も変更されません。私はjsfiddle.net/markcoleman/fMP9s/1のリンカーを使用して変更しました。link:function(scope、element、attrs){element [0] .outerHTML = ''; $ compile(element.contents())(scope); }
Lauri Lubi、

1

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

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


2012年のコメント。これはまだ事実ですか?ドキュメントを検索しようとしましたが、参照が見つかりませんでした。
ザックS

1

これを行うためのAngularの魔法の方法はありません。あなたのケースでは、Bootstrapを使用している場合、有効なHTMLを取得するためにこれを行うことができます。その後、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>

1

実際に機能するソリューション

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>開始要素と終了要素を<!--removed element-->


これは面白い。ただし、私のテストでreplaceWith(...)は、コメントではなくテキストノードが生成されます。element.remove()作品を使っているだけです。
artfulrobot
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.