数値と範囲を持つAngularJS Forループ


252

Angularは、HTMLディレクティブ内で数値を使用するforループをサポートしています。

<div data-ng-repeat="i in [1,2,3,4,5]">
  do something
</div>

ただし、スコープ変数に動的な数値の範囲が含まれている場合は、毎回空の配列を作成する必要があります。

コントローラ内

var range = [];
for(var i=0;i<total;i++) {
  range.push(i);
}
$scope.range = range;

HTMLで

<div data-ng-repeat="i in range">
  do something
</div>

これは機能しますが、範囲配列をループ内でまったく使用しないため、これは不要です。誰かが最小値/最大値の範囲または規則を設定することを知っていますか?

何かのようなもの:

<div data-ng-repeat="i in 1 .. 100">
  do something
</div>

2
これに関する詳細は次のとおりです。yearofmoo.com/2012/10/...
matsko

回答:


281

私はこの答えを少し調整して、このフィドルを思いつきました。

次のように定義されたフィルター:

var myApp = angular.module('myApp', []);
myApp.filter('range', function() {
  return function(input, total) {
    total = parseInt(total);

    for (var i=0; i<total; i++) {
      input.push(i);
    }

    return input;
  };
});

このように使用される繰り返しで:

<div ng-repeat="n in [] | range:100">
  do something
</div>

興味深いことに、Chromeを使用しているフィドルでエラーが表示されません。どのブラウザ?
Gloopy、2013年

5
恐ろしい!;)フィルターはこれを行う方法ではありません。2つの値で機能する新しい属性である必要があります。現在のインデックスと上限。
Ian Warburton

10
@IanWarburtonあなたはあなたの基準を満たす答えを思いつくことができますか?
dewd、2013年

1
@IanWarburton:ディレクティブで動作する以下のУmedによる回答がありますが、動作させることができません。
Andresch Serj 2014年

1
私はAとBの間の範囲が必要だったので、この答えjsfiddle.net/h9nLc8mkを使いました
Marcio

150

たとえば、2つの定義された数値の間の範囲を作成するために、さらに単純なバージョンを考え出しました。5から15

JSFiddleのデモを見る

HTML

<ul>
    <li ng-repeat="n in range(5,15)">Number {{n}}</li>
</ul>

コントローラー

$scope.range = function(min, max, step) {
    step = step || 1;
    var input = [];
    for (var i = min; i <= max; i += step) {
        input.push(i);
    }
    return input;
};

14
このようなことに注意する必要があります。範囲関数は、リスト内の各アイテムに対して複数回呼び出されます。厄介なメモリリークが発生する可能性があり、多くの関数呼び出しが生成されます。コントローラー内にコレクションを配置する方が簡単なようです。
Lucas Holt

1
var a; void 0 === a「本当に」未定義。
andlrc 2014

1
memoizerパターンを介して結果をキャッシュすることにより、パフォーマンスヒットを減らすことができます。メモリコストがどの程度かはわかりませんが、それは改善です。en.wikipedia.org/wiki/Memoization
ジョシュア

1
@LucasHoltようやくこの例の更新に取り掛かりました。最適化されたバージョンを追加しました。それでも多くの関数呼び出しがありますが、最初の結果を再利用するため、パフォーマンスが大幅に向上します。
sqren 2015年

93

プレーンなJavascript以外は何もありません(コントローラーも必要ありません)。

<div ng-repeat="n in [].constructor(10) track by $index">
    {{ $index }}
</div>

モックアップ時に非常に役立ちます


Angularで動作しない> 1.2.1:コンソールにこのエラーがありReferencing "constructor" field in Angular expressions is disallowed! Expression: [].constructor(10)ます。多分それはAngularの以前のバージョンで働いていたのか、私は何か間違ったことをしています。
AWolf 2015

私はこれを1.3または1.4でテストしましたが、問題はありませんでした。私はそれらがパーサーを改善したので、すべての「コンストラクター」アクセスを拒否するのではなく、本当に危険なもの(たとえば[].slice.constructor、にアクセスするFunctionため、コード評価にアクセスする)のみを拒否します。
MAEL二尊院

わかりました。1.2.1でテストしましたが、機能しませんでした(jsFiddleドロップダウンに含まれているバージョン)。しかし、1.3.15では動作しています。このjsFiddleを参照してください
AWolf 2015

ページネーションに非常に役立ちます。ありがとう;)
見知らぬ人

69

私は少しだけ私に合ったわずかに異なる構文を考え出し、オプションで下限も追加しました:

myApp.filter('makeRange', function() {
        return function(input) {
            var lowBound, highBound;
            switch (input.length) {
            case 1:
                lowBound = 0;
                highBound = parseInt(input[0]) - 1;
                break;
            case 2:
                lowBound = parseInt(input[0]);
                highBound = parseInt(input[1]);
                break;
            default:
                return input;
            }
            var result = [];
            for (var i = lowBound; i <= highBound; i++)
                result.push(i);
            return result;
        };
    });

あなたはそれとして使うことができます

<div ng-repeat="n in [10] | makeRange">Do something 0..9: {{n}}</div>

または

<div ng-repeat="n in [20, 29] | makeRange">Do something 20..29: {{n}}</div>

これは素晴らしいですが$digest、スコープ付きの値を使用する場合、どのようにしてすべての反復を回避できますng-repeat="n in [1, maxValue] | makeRange"か。
pspahn 2015年

1つと2つのparamケースでは、highBoundの扱いが異なります。一貫している必要があります
Vajk Hermecz

31

angularjsを初めて使う人のために。インデックスは$ indexを使用して取得できます。

例えば:

<div ng-repeat="n in [] | range:10">
    do something number {{$index}}
</div>

あなたはGloopyの便利なフィルタを使用しているときには、印刷されます:
何か番号0
何か番号1
何か番号2
何か番号3
何か番号4
何か番号5
何か番号6
何か番号7
何か数8
何か9をします


7
本当ですが、この場合do something number {{n}}も十分です。
captncraig 2013年

2
Chromeでこのコードを実行しようとすると、コンソールにエラーが表示されます。エラー:[$ injector:unpr] errors.angularjs.org/1.2.6/$injector/… ... ... at Wa.statements(ajax.googleapis.com/ajax/libs/angularjs/1.2.6/…)<!-ngRepeat:n in [] | range:10->(残念ながら、エラー全体が長すぎて許容されるコメント長に収まらないため、最初と最後の行をコピーしました)
Kmeixner

1
コードと比較できるように、コードのPlunkerサンプルを作成しました。plnkr.co/edit/tN0156hRfX0M6k9peQ2C?p=preview
Arnoud Sietsema

21

これを行う簡単な方法は、Underscore.jsの_.range()メソッドを使用することです。:)

http://underscorejs.org/#range

// declare in your controller or wrap _.range in a function that returns a dynamic range.
var range = _.range(1, 11);

// val will be each number in the array not the index.
<div ng-repeat='val in range'>
    {{ $index }}: {{ val }}
</div>

1
@jwoodward彼はそれが選択肢ではないと言ったことはありません。私のソリューションは、リポジトリからのユニットテストのおかげで、群を抜いて最もシンプルで最もテストされています。いつでもjsを非縮小ライブラリから取り出し、関数として含めることができます。
Michael J. Calkins 2013年

4
確かに、彼はそんなことを言ったことはありません。ただし、あるライブラリの問題を別のライブラリを適用して解決することは、一般的には悪い考えです。最初のライブラリの使い方を正しく理解できなくなるだけです。現在のライブラリに適切な解決策がない場合は、別のライブラリに切り替えます。
Erik Honn

5
私はすでにどこでもlodashを使用していますが、これが最も簡単な解決策でした。ありがとうございました。$ scope.range = _.rangeを実行しただけで、動的な開始/終了値を持つ任意のテンプレートで簡単に使用できます。
j_walker_dev 2014年

2
@ErikHonn:UnderscoreJSは、AngularJSとはまったく異なる問題を解決します。これはライブラリの目的ではないため、AngularJSで範囲を生成するための適切なソリューションはありません。
AlexFoxGill 2014年

2
これは古いですが、現在のライブラリの機能を非セマンティックな方法で悪用するのではなく、範囲の作成とまったく同じように設計されたライブラリを使用する方がはるかに良い方法ですか?確かにあなたは何かを学ぶかもしれませんが、あなたは何か他のもののために設計されたものの歪んだ使用法に終わります。
Dan

20

カスタムng-repeat-rangeディレクティブを使用します。

/**
 * Ng-Repeat implementation working with number ranges.
 *
 * @author Umed Khudoiberdiev
 */
angular.module('commonsMain').directive('ngRepeatRange', ['$compile', function ($compile) {
    return {
        replace: true,
        scope: { from: '=', to: '=', step: '=' },

        link: function (scope, element, attrs) {

            // returns an array with the range of numbers
            // you can use _.range instead if you use underscore
            function range(from, to, step) {
                var array = [];
                while (from + step <= to)
                    array[array.length] = from += step;

                return array;
            }

            // prepare range options
            var from = scope.from || 0;
            var step = scope.step || 1;
            var to   = scope.to || attrs.ngRepeatRange;

            // get range of numbers, convert to the string and add ng-repeat
            var rangeString = range(from, to + 1, step).join(',');
            angular.element(element).attr('ng-repeat', 'n in [' + rangeString + ']');
            angular.element(element).removeAttr('ng-repeat-range');

            $compile(element)(scope);
        }
    };
}]);

そしてhtmlコードは

<div ng-repeat-range from="0" to="20" step="5">
    Hello 4 times!
</div>

または単に

<div ng-repeat-range from="5" to="10">
    Hello 5 times!
</div>

または単に

<div ng-repeat-range to="3">
    Hello 3 times!
</div>

あるいは単に

<div ng-repeat-range="7">
    Hello 7 times!
</div>

1
理論的にはいいのですが、インジェクションはelement.attr('ng-repeat', 'n in [' + rangeString + ']');機能しません...
Stefan Walther

"私が使う..."。実際に使ってみましたか?ng-repeat属性はコンパイルされません。
Peter Hedberg 2014

ピーターに感謝し、アイブはコードを更新しました。私は過去にこのディレクティブを使用しましたが、それでもコードリポジトリが残りました
pleerock '29

9

最も簡単なコードソリューションは、範囲を指定して配列を初期化し、$ index +を使用することでした。

<select ng-init="(_Array = []).length = 5;">
    <option ng-repeat="i in _Array track by $index">{{$index+5}}</option>
</select>

7

メソッド定義

以下のコードrange()は、アプリケーションのスコープ全体で使用できるメソッドを定義していますMyApp。その動作はPython range()メソッドに非常に似ています。

angular.module('MyApp').run(['$rootScope', function($rootScope) {
    $rootScope.range = function(min, max, step) {
        // parameters validation for method overloading
        if (max == undefined) {
            max = min;
            min = 0;
        }
        step = Math.abs(step) || 1;
        if (min > max) {
            step = -step;
        }
        // building the array
        var output = [];
        for (var value=min; value<max; value+=step) {
            output.push(value);
        }
        // returning the generated array
        return output;
    };
}]);

使用法

1つのパラメーターを使用:

<span ng-repeat="i in range(3)">{{ i }}, </span>

0, 1, 2,

2つのパラメーター:

<span ng-repeat="i in range(1, 5)">{{ i }}, </span>

1, 2, 3, 4,

3つのパラメーター:

<span ng-repeat="i in range(-2, .7, .5)">{{ i }}, </span>

-2, -1.5, -1, -0.5, 0, 0.5,


6

angular.filterモジュール(「https://github.com/a8m/angular-filter」)で「後」または「前」フィルターを使用できます

$scope.list = [1,2,3,4,5,6,7,8,9,10]

HTML:

<li ng-repeat="i in list | after:4">
  {{ i }}
</li>

結果: 5、6、7、8、9、10


6

コントローラーを変更せずに、これを使用できます。

ng-repeat="_ in ((_ = []) && (_.length=51) && _) track by $index"

楽しい!


1日以上も苦労していて、ついにこの構文だけが
うまくいっ

3

最短の回答:2行のコード

JS(AngularJSコントローラー内)

$scope.range = new Array(MAX_REPEATS); // MAX_REPEATS should be the most repetitions you will ever need in a single ng-repeat

HTML

<div data-ng-repeat="i in range.slice(0,myCount) track by $index"></div>

...どこ myCountこの場所に表示されるはずの星の数です。

$index追跡操作に使用できます。たとえば、インデックスに変更を出力する場合は、次のように記述しますdiv

{{ ($index + 1) * 0.5 }}

2

UnderscoreJSの使用:

angular.module('myModule')
    .run(['$rootScope', function($rootScope) { $rootScope.range = _.range; }]);

これを適用して$rootScope、どこでも使用できるようにします。

<div ng-repeat="x in range(1,10)">
    {{x}}
</div>

2

非常にシンプルなもの:

$scope.totalPages = new Array(10);

 <div id="pagination">
    <a ng-repeat="i in totalPages track by $index">
      {{$index+1}}
    </a>   
 </div> 

2

こんにちは、AngularJSを使用して純粋なhtmlを使用してこれを達成できます(ディレクティブは必要ありません!)

<div ng-app="myapp" ng-controller="YourCtrl" ng-init="x=[5];">
  <div ng-if="i>0" ng-repeat="i in x">
    <!-- this content will repeat for 5 times. -->
    <table class="table table-striped">
      <tr ng-repeat="person in people">
         <td>{{ person.first + ' ' + person.last }}</td>
      </tr>
    </table>
    <p ng-init="x.push(i-1)"></p>
  </div>
</div>

1

コントローラーにスコープを設定

var range = [];
for(var i=20;i<=70;i++) {
  range.push(i);
}
$scope.driverAges = range;

HTMLテンプレートファイルで繰り返しを設定

<select type="text" class="form-control" name="driver_age" id="driver_age">
     <option ng-repeat="age in driverAges" value="{{age}}">{{age}}</option>
</select>

1

@モルメジルのソリューションの改善

app.filter('makeRange', function() {
  return function(inp) {
    var range = [+inp[1] && +inp[0] || 0, +inp[1] || +inp[0]];
    var min = Math.min(range[0], range[1]);
    var max = Math.max(range[0], range[1]);
    var result = [];
    for (var i = min; i <= max; i++) result.push(i);
    if (range[0] > range[1]) result.reverse();
    return result;
  };
});

使用法

<span ng-repeat="n in [3, -3] | makeRange" ng-bind="n"></span>

3 2 1 0 -1 -2 -3

<span ng-repeat="n in [-3, 3] | makeRange" ng-bind="n"></span>

-3 -2 -1 0 1 2 3

<span ng-repeat="n in [3] | makeRange" ng-bind="n"></span>

0 1 2 3

<span ng-repeat="n in [-3] | makeRange" ng-bind="n"></span>

0 -1 -2 -3


1

私は以下を試しましたが、それは私にとってはうまくいきました:

<md-radio-button ng-repeat="position in formInput.arrayOfChoices.slice(0,6)" value="{{position}}">{{position}}</md-radio-button>

Angular 1.3.6


1

パーティーに遅れました。しかし、私はこれをやっただけです:

コントローラで:

$scope.repeater = function (range) {
    var arr = []; 
    for (var i = 0; i < range; i++) {
        arr.push(i);
    }
    return arr;
}

HTML:

<select ng-model="myRange">
    <option>3</option>
    <option>5</option>
</select>

<div ng-repeat="i in repeater(myRange)"></div>

1

これはjzmの改善された回答です(他にコメントすることはできませんが、エラーが含まれているため、彼女/彼の回答にコメントします)。関数には開始/終了範囲の値があるため、より柔軟であり、...機能します。この特定のケースは月の日です:

$scope.rangeCreator = function (minVal, maxVal) {
    var arr = [];
   for (var i = minVal; i <= maxVal; i++) {
      arr.push(i);
   }
   return arr;
};


<div class="col-sm-1">
    <select ng-model="monthDays">
        <option ng-repeat="day in rangeCreator(1,31)">{{day}}</option>
    </select>
</div>

0

私はこれをホイップして、それが一部にとって有用であるかもしれないのを見ました。(はい、CoffeeScript。私を訴えます。)

指令

app.directive 'times', ->
  link: (scope, element, attrs) ->
    repeater = element.html()
    scope.$watch attrs.times, (value) ->
      element.html ''
      return unless value?
      element.html Array(value + 1).join(repeater)

使用するには:

HTML

<div times="customer.conversations_count">
  <i class="icon-picture></i>
</div>

これはもっと簡単になりますか?

Angularは常に正当な理由なくフィルターを再評価することを好むため、フィルターについては注意が必要です。

このディレクティブはモデルの変更を監視し、それに応じて要素を更新します。


これは便利ですが、ngRepeatは独自のスコープを維持します。そのため、追加されたアイテムごとにコンパイルを実行する必要があります。ngRepeatがアニメーションをエミュレートするため、アニメーションをエミュレートする必要もあります。
matsko 2013年

2
貢献していただきありがとうございます。ただし、OPがcoffeescriptとは何か、それをJSにコンパイルする方法を知っている、またはそのようなビルドツールを使用したことがあると想定すると、非常に大きな負担になります。私たちはみな学び、手助けするためにここにいるので、さらに一歩進んで、その子犬を改宗させましょう。(あなたは訴えられました!)
Augie Gardner 14

0
<div ng-init="avatars = [{id : 0}]; flag = true ">
  <div ng-repeat='data in avatars' ng-if="avatars.length < 10 || flag"
       ng-init="avatars.length != 10 ? avatars.push({id : $index+1}) : ''; flag = avatars.length <= 10 ? true : false">
    <img ng-src="http://actual-names.com/wp-content/uploads/2016/01/sanskrit-baby-girl-names-400x275.jpg">
  </div>
</div>

コントローラーやファクトリーなしでhtmlでこれを実現したい場合。


0

次に$scope.refernceurl、配列であるとします

for(var i=0; i<$scope.refernceurl.length; i++){
    $scope.urls+=$scope.refernceurl[i].link+",";
}

-8

これは最も単純なバリアントです。整数の配列を使用するだけです...

 <li ng-repeat="n in [1,2,3,4,5]">test {{n}}</li>


3
これは恐ろしいことです。
Tiffany Lowe、

@Stefan、ソリューションはハードコードされたコレクションを使用できないため、おそらく反対票を受け取ります。
Tass
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.