148

ng-repeat配列内のすべての要素を一覧表示するには、(AngularJSで)を使用する必要があります。

複雑なのは、配列の各要素がテーブルの1行、2行、または3行に変換されることです。

との間でng-repeat繰り返し要素のタイプが許可されていないため、要素で使用されている場合、有効なhtmlを作成できません。<tbody><tr>

たとえば、でng-repeatを使用した場合、次のよう<span>になります。

<table>
  <tbody>
    <span>
      <tr>...</tr>
    </span>
    <span>
      <tr>...</tr>
      <tr>...</tr>
      <tr>...</tr>
    </span>
    <span>
      <tr>...</tr>
      <tr>...</tr>
    </span>
  </tbody>
</table>          

これは無効なhtmlです。

しかし、私が生成する必要があるのは次のとおりです。

<table>
  <tbody>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
  </tbody>
</table>          

ここで、最初の行は最初の配列要素によって生成され、次の3つは2番目の配列要素によって生成され、5番目と6番目は最後の配列要素によって生成されています。

レンダリング中にバインドされているhtml要素が「消える」ようにng-repeatを使用するにはどうすればよいですか?

または、これに対する別の解決策はありますか?


明確化:生成された構造は次のようになります。各配列要素は、テーブルの1〜3行を生成できます。答えは、理想的には配列要素ごとに0〜n行をサポートする必要があります。

<table>
  <tbody>
    <!-- array element 0 -->
    <tr>
      <td>One row item</td>
    </tr>
    <!-- array element 1 -->
    <tr>
      <td>Three row item</td>
    </tr>
    <tr>
      <td>Some product details</td>
    </tr>
    <tr>
      <td>Customer ratings</td>
    </tr>
    <!-- array element 2 -->
    <tr>
      <td>Two row item</td>
    </tr>
    <tr>
      <td>Full description</td>
    </tr>
  </tbody>
</table>          
4

8 に答える 8

71

AngularJS 1.2 の時点で、ng-repeat-startまさにあなたが求めていることを実行するというディレクティブがあります。使用方法の説明については、この質問の私の回答を参照してください。

于 2013-09-17T06:57:00.783 に答える
68

更新: Angular 1.2+ を使用している場合は、ng-repeat-start を使用してください。@jmagnussonの回答を参照してください。

それ以外の場合は、tbody に ng-repeat を配置するのはどうですか? (私の知る限り、単一のテーブルに複数の <tbody> を含めても問題ありません。)

<tbody ng-repeat="row in array">
  <tr ng-repeat="item in row">
     <td>{{item}}</td>
  </tr>
</tbody>
于 2012-08-16T20:39:49.557 に答える
37

ng > 1.2 を使用する場合、ng-repeat-start/end不要なタグを生成せずに使用する例を次に示します。

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script>
      angular.module('mApp', []);
    </script>
  </head>
  <body ng-app="mApp">
    <table border="1" width="100%">
      <tr ng-if="0" ng-repeat-start="elem in [{k: 'A', v: ['a1','a2']}, {k: 'B', v: ['b1']}, {k: 'C', v: ['c1','c2','c3']}]"></tr>

      <tr>
        <td rowspan="{{elem.v.length}}">{{elem.k}}</td>
        <td>{{elem.v[0]}}</td>
      </tr>
      <tr ng-repeat="v in elem.v" ng-if="!$first">
        <td>{{v}}</td>
      </tr>

      <tr ng-if="0" ng-repeat-end></tr>
    </table>
  </body>
</html>

ng-repeat-start重要なポイント:およびng-repeat-endsetに使用されるタグについてng-if="0"は、ページに挿入しないようにします。このようにして、内部コンテンツは( のコマンドを使用して<!--...-->)knockoutjs とまったく同じように処理され、ゴミはなくなります。

于 2015-07-10T15:09:08.107 に答える
20

コントローラー内のデータをフラット化することができます。

function MyCtrl ($scope) {
  $scope.myData = [[1,2,3], [4,5,6], [7,8,9]];
  $scope.flattened = function () {
    var flat = [];
    $scope.myData.forEach(function (item) {
      flat.concat(item);
    }
    return flat;
  }
}

そしてHTMLで:

<table>
  <tbody>
    <tr ng-repeat="item in flattened()"><td>{{item}}</td></tr>
  </tbody>
</table>
于 2012-07-15T19:23:22.793 に答える
9

上記は正しいですが、より一般的な答えには十分ではありません。ng-repeat をネストする必要がありましたが、同じ html レベルに留まる必要がありました。つまり、同じ親に要素を書き込むということです。tags 配列には、tags 配列も持つタグが含まれています。実は木です。

[{ name:'name1', tags: [
  { name: 'name1_1', tags: []},
  { name: 'name1_2', tags: []}
  ]},
 { name:'name2', tags: [
  { name: 'name2_1', tags: []},
  { name: 'name2_2', tags: []}
  ]}
]

だからここに私が最終的にやったことです。

<div ng-repeat-start="tag1 in tags" ng-if="false"></div>
    {{tag1}},
  <div ng-repeat-start="tag2 in tag1.tags" ng-if="false"></div>
    {{tag2}},
  <div ng-repeat-end ng-if="false"></div>
<div ng-repeat-end ng-if="false"></div>

開始 div と終了 div を非表示にする ng-if="false" に注意してください。

印刷する必要があります

名前1,名前1_1,名前1_2,名前2,名前2_1,名前2_2,

于 2015-08-14T12:25:58.410 に答える
1

コメントしたいだけですが、私の評判はまだ不足しています。そのため、問題も解決する別のソリューションを追加しています。この問題を解決するには「せいぜいハック」ソリューションが必要であるという @bmoeskau の声明に反論したいと思います。この投稿は 2 年前のものですが、最近の議論で話題になったので、私の意見を追加したいと思います。 2 セントを所有する:

@btford が指摘したように、再帰構造をリストに変換しようとしているように見えるため、最初にその構造をリストにフラット化する必要があります。彼のソリューションはそれを行いますが、テンプレート内で関数を呼び出すのはエレガントではないという意見があります。それが本当なら(正直なところ、私にはわかりません)、ディレクティブではなくコントローラーで関数を実行するだけでよいでしょうか?

いずれにせよ、HTML にはリストが必要なので、それをレンダリングするスコープには、そのリストを操作する必要があります。コントローラー内の構造を平坦化するだけです。$scope.rows 配列を取得したら、単一の単純な ng-repeat でテーブルを生成できます。ハッキングもなく、優雅さもなく、単に設計どおりに動作します。

Angulars ディレクティブには機能が欠けているわけではありません。有効な html を書くよう強制するだけです。私の同僚も同様の問題を抱えており、@bmoeskau を引用して、angular のテンプレート化/レンダリング機能に対する批判を支持しています。正確な問題を見ると、彼は単に開始タグを生成し、次に別の場所で終了タグを生成したかっただけであることがわかりました.ちょうど古き良き時代のように、文字列からhtmlを連結していました..そうですか? 番号。

構造をリストにフラット化することに関しては、別の解決策があります:

// assume the following structure
var structure = [
    {
        name: 'item1', subitems: [
            {
                name: 'item2', subitems: [
                ],
            }
        ],
    }
];
var flattened = structure.reduce((function(prop,resultprop){
    var f = function(p,c,i,a){
        p.push(c[resultprop]);
        if (c[prop] && c[prop].length > 0 )
          p = c[prop].reduce(f,p);
        return p;
    }
    return f;
})('subitems','name'),[]);

// flattened now is a list: ['item1', 'item2']

これは、サブアイテムを持つツリー状の構造で機能します。プロパティではなくアイテム全体が必要な場合は、フラット化関数をさらに短縮できます。

それが役立つことを願っています。

于 2015-09-30T10:09:00.080 に答える
-2
<table>
  <tbody>
    <tr><td>{{data[0].foo}}</td></tr>
    <tr ng-repeat="d in data[1]"><td>{{d.bar}}</td></tr>
    <tr ng-repeat="d in data[2]"><td>{{d.lol}}</td></tr>
  </tbody>
</table>

これは有効だと思います:)

于 2012-07-15T16:31:57.653 に答える