1. ホーム
  2. javascript

[解決済み] ng-repeatのデータをブートストラップで3列に分割する方法

2022-08-03 02:15:57

質問

私は自分のコードでng-repeatを使用しています。ng-repeatに基づいてテキストボックスを「n」個持っています。私は3つの列でテキストボックスを整列させたいと思います。

これは私のコードです。

<div class="control-group" ng-repeat="oneExt in configAddr.ext">
    {{$index+1}}. 
    <input type="text" name="macAdr{{$index+1}}" 
           id="macAddress" ng-model="oneExt.newValue" value=""/>
</div>

どのように解決するのですか?

最も信頼性が高く、技術的に正しい方法は、コントローラ内でデータを変換することです。ここでは、簡単なチャンク関数と使い方を紹介します。

function chunk(arr, size) {
  var newArr = [];
  for (var i=0; i<arr.length; i+=size) {
    newArr.push(arr.slice(i, i+size));
  }
  return newArr;
}

$scope.chunkedData = chunk(myData, 3);

そうすると、ビューは次のようになります。

<div class="row" ng-repeat="rows in chunkedData">
  <div class="span4" ng-repeat="item in rows">{{item}}</div>
</div>

の中に入力がある場合は ng-repeat の中に入力がある場合、データが変更されたときや送信されたときに、おそらく配列のチャンクや再接続を行いたいでしょう。これは $watch で、データが常に元のマージされたフォーマットで利用できるようにします。

$scope.$watch('chunkedData', function(val) {
  $scope.data = [].concat.apply([], val);
}, true); // deep watch

多くの人は、ビューの中でフィルタを使ってこれを達成することを好みます。これは可能ですが、表示目的のみに使用すべきです! このフィルタリングされたビューの中で入力を追加すると、次のような問題が発生します。 ができます。 は解決されますが きれいでも信頼できるものでもない .

このフィルタの問題は、毎回新しいネストされた配列を返してくることです。Angularはフィルターからの戻り値を監視しています。最初にフィルタが実行されたとき、Angularはその値を知っています。その後、フィルタが変更されたことを確認するために再度実行します。両方の値が同じであれば、サイクルは終了します。もし同じでなければ、同じ値になるまで何度もフィルタが実行され、無限ダイジェストループが発生していることに気づいてシャットダウンします。新しいネストされた配列やオブジェクトは以前はAngularによって追跡されていなかったため、Angularは常に戻り値が以前と異なるものとして認識します。このような "unstable" なフィルタを修正するには、そのフィルタを memoize 関数で囲みます。 lodash には memoize という関数があり、lodashの最新版でも chunk 関数も含まれているので、このフィルターは非常にシンプルに npm モジュールを使い、スクリプトをコンパイルする際に browserify または webpack .

覚えておいてください: 表示のみ! 入力を使用する場合は、コントローラでフィルタリングしてください!

lodashをインストールします。

npm install lodash-node

フィルタを作成します。

var chunk = require('lodash-node/modern/array/chunk');
var memoize = require('lodash-node/modern/function/memoize');

angular.module('myModule', [])
.filter('chunk', function() {
  return memoize(chunk);
});

そして、このフィルタを使ったサンプルです。

<div ng-repeat="row in ['a','b','c','d','e','f'] | chunk:3">
  <div class="column" ng-repeat="item in row">
    {{($parent.$index*row.length)+$index+1}}. {{item}}
  </div>
</div>

項目を縦に並べる

1  4
2  5
3  6

水平方向(左から右)ではなく垂直方向の列(リストの上から下)に関して、正確な実装は望ましいセマンティクスに依存します。不均等に分割されたリストは、様々な方法で配布することができます。ここでは、1つの方法を紹介します。

<div ng-repeat="row in columns">
  <div class="column" ng-repeat="item in row">
    {{item}}
  </div>
</div>

var data = ['a','b','c','d','e','f','g'];
$scope.columns = columnize(data, 3);
function columnize(input, cols) {
  var arr = [];
  for(i = 0; i < input.length; i++) {
    var colIdx = i % cols;
    arr[colIdx] = arr[colIdx] || [];
    arr[colIdx].push(input[i]);
  }
  return arr;
}

しかし、カラムを取得するための最も直接的で単純な方法は CSS columns :

.columns {
  columns: 3;
}

<div class="columns">
  <div ng-repeat="item in ['a','b','c','d','e','f','g']">
    {{item}}
  </div>
</div>