简体   繁体   English

如何使用angularjs中的ng-repeat迭代JavaScript Maps?

[英]How to iterate through JavaScript Maps using ng-repeat in angularjs?

I'm trying to use JavaScript Maps in ng-repeat angular's directive while searching I found that it could be done this way : 我正在尝试在搜索时使用ng-repeat angular指令中的JavaScript Maps我发现它可以这样做:

<ul ng-controller="MyCtrl">
    <li ng-repeat='(key, value) in {"First Name":"John", "Last Name":"Smith"}'>
        <span>Key: {{key}}, value: {{value}}</span>
    </li>
</ul>

but this works only with normal JSON objects, when I create a real Map the following way, it doesn't work. 但是这只适用于普通的JSON对象,当我以下面的方式创建一个真实的Map时,它不起作用。

I have this controller for example 我有这个控制器

function MyCtrl($scope) {
    $scope.items = new map();
    $scope.items.set('adam',{'age':10,'fav':'doogie'});
    $scope.items.set('amalie',{'age':12});
}

and this html code 和这个HTML代码

<ul>
    <li ng-repeat='(key, value) in items'>
        <span>Key: {{key}}, value: {{value}}</span>
    </li>
</ul>

since ng-repeat not support Map iteration, you could use a custom filter fromMap like below 由于ng-repeat不支持Map迭代,您可以使用fromMap的自定义过滤器,如下所示

 angular.module('app', []).filter('fromMap', function() { return function(input) { var out = {}; input.forEach((v, k) => out[k] = v); return out; }; }).controller('ctrl',function ($scope) { $scope.items = new Map(); $scope.items.set('adam',{'age':10,'fav':'doogie'}); $scope.items.set('amalie',{'age':12}); $scope.logAdamAge = function() { console.log($scope.items.get("adam").age) }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="app" ng-controller="ctrl"> <div>with Map</div> <ul> <li ng-repeat="(key, value) in items | fromMap"> <div>{{key}}</div> <div ng-repeat="(k, v) in value">{{k}}: <input ng-model="value[k]" /></div> </li> </ul> <pre>{{items | fromMap}}</pre> <button ng-click="logAdamAge()">log Adam age from Map</button> </div> 

this won't work because a javascript Map is an iterable object (you can loop over only through the entries iterator, calling a next() each time) and is not directly supported by angular ng-repeat . 这是行不通的,因为javascript Map是一个可迭代的对象(你可以只通过条目迭代器循环,每次调用next())并且不受角度ng-repeat直接支持。

what you can do if you have a pre-existent code is to transform the iterable object (map) to a plain array 如果你有一个预先存在的代码,你可以做的是将可迭代对象(map)转换为普通数组

$scope.itemsToArray = Array.from($scope.items.entries()); 

this will make your iterable object an array , at this point you can loop over in the standard way 这将使您的可迭代对象成为一个数组,此时您可以以标准方式循环

<ul>  
  <li ng-repeat='item in itemsToArray'>
     <span>Key: {{item[0]}}, value: {{item[1]}}</span>
  </li>
</ul>

working plnkr here 这里工作的plnkr

Although I like Jag's answer , I've built a more extensive snippet with different implementations to achieve the same, and I took out the most of ES6 arrow functions and spread operator to implement the filter as a one-liner: .filter('fromMap', () => mapObject => [...mapObject]) 虽然我喜欢Jag的答案 ,但我已经构建了一个更广泛的不同实现的片段来实现相同的目标,并且我拿出了大部分ES6箭头函数和扩展运算符来实现过滤器作为单行: .filter('fromMap', () => mapObject => [...mapObject])

One setting a watcher and even unsuscribing to that watcher. 一个设置观察者,甚至没有描述观察者。

Here is how you can implement ng-repeat on Map class objects: 以下是如何在Map类对象上实现ng-repeat的方法:

 angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']); angular.module('ui.bootstrap.demo') .filter('fromMap', () => mapObject => [...mapObject]) .controller('myCtrl', function($scope, $log) { $scope.myMap = new Map([ ['key1', 'value1'], ['key2', 'value2'], ['key3', 'value3'], ['key4', 'value4'], ]); const unsuscribeWatcher1 = $scope.$watch(() => $scope.myMap.size, (newVal, oldVal) => { if (newVal !== oldVal) { //Splicing and pushing keeps the reference to the Array instead of reassigning. $scope.myLoopedMap.splice(0); $scope.myLoopedMap.push(...[...$scope.mySet].filter(k => $scope.myMap.has(k)).map(k => $scope.myMap.get(k))) $scope.myArrFromMap.splice(0); $scope.myArrFromMap.push(...[...$scope.myMap]) } }) const unsuscribeWatcher2 = $scope.$watch(() => $scope.mySet.size, (newVal, oldVal) => { if (newVal !== oldVal) { $scope.myLoopedMap.splice(0); $scope.myLoopedMap.push([...$scope.mySet].filter(k => $scope.myMap.has(k)).map(k => $scope.myMap.get(k))); } }) $scope.mySet = new Set(['key1', 'key3']); $scope.mySet.add('not in the Map') $scope.mySet.add('key7') $scope.myKeys = ['key1', 'key3']; $scope.myArr = [ ['key1', 'value1'], ['key2', 'value2'], ['key3', 'value3'], ['key4', 'value4'], ]; $scope.myArrFromMap = [...$scope.myMap] $scope.myLoopedMap = [...$scope.mySet].filter(k => $scope.myMap.has(k)).map(k => $scope.myMap.get(k)) $scope.myLoopedMap2 = [...$scope.myKeys].reduce((acc, k) => { return $scope.myMap.has(k) ? acc.concat($scope.myMap.get(k)) : acc; }, []) // added to the map later setTimeout(() => { $scope.$apply(() => { // this will be updated as we are watching the Map $scope.myMap.set('key7', 'value7') }) setTimeout(() => { unsuscribeWatcher1(); // this breaks the watching of the Map $scope.$apply(() => { // this will not be updated as the watcher is not working anymore $scope.myMap.set('key8', 'value8') }) }, 3000) }, 3000) }); 
 <!doctype html> <html ng-app="ui.bootstrap.demo"> <head> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script> <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script> <script src="example.js"></script> </head> <body> <div ng-controller="myCtrl"> <h3>Some test data data</h3> <div>Get 'key1'======> {{myMap.get('key1')}}</div> <div>Arr ==========> {{myArr}}</div> <div>filtered ======> {{myMap | fromMap}}</div> <div>myArrFromMap=> {{myArrFromMap}}</div> <div>myLoopedMap==> {{myLoopedMap}}</div> <div>myLoopedMap2=> {{myLoopedMap2}}</div> <h3>ng repeat in myLoopedMap</h3> <div ng-repeat="item in myLoopedMap"> Item:`{{item}}` </div> <h3>ng repeat in myArrFromMap</h3> <div ng-repeat="(index, value) in myArrFromMap"> value[0]:`{{value[0]}}`, value[1]:`{{value[1]}}`, index: `{{index}}` </div> </div> </body> </html> 

And the corresponding Plnkr 相应的Plnkr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM