วิธีกรอง (คีย์ค่า) ด้วย ng-repeat ใน AngularJs


113

ฉันกำลังพยายามทำสิ่งที่ชอบ:

<div ng-controller="TestCtrl">
    <div ng-repeat="(k,v) in items | filter:hasSecurityId">
        {{k}} {{v.pos}}
    </div>
</div>

AngularJs ส่วน:

function TestCtrl($scope) 
{
    $scope.items = {
                     'A2F0C7':{'secId':'12345', 'pos':'a20'},
                     'C8B3D1':{'pos':'b10'}
                   };

    $scope.hasSecurityId = function(k,v)
    {
       return v.hasOwnProperty('secId');
    }
}

แต่อย่างใดมันแสดงให้ฉันเห็นทุกรายการ ฉันจะกรอง (คีย์ค่า) ได้อย่างไร


โปรดให้ตัวอย่างข้อมูล fot หรือให้เราเล่นซอ;)
Robin Drexler

นี่ไม่ใช่วิธีที่คุณสร้างตัวกรองดูเอกสารและตามที่โรบินกล่าวไว้โปรดดูตัวอย่าง
Yahya KACEM

ฉันได้ยกตัวอย่างทั้งหมดแล้วและฉันรู้วิธีใช้ตัวกรอง ฉันแค่ถาม "วิธีใช้ตัวกรองด้วย (คีย์ค่า)"
Vural

ดัชนีและจำนวนควรมีอยู่ในขอบเขตนั้น
Shanimal

คำตอบ:


131

ตัวกรองเชิงมุมสามารถใช้ได้กับอาร์เรย์เท่านั้นไม่ใช่วัตถุจาก API ของเชิงมุม -

"เลือกชุดย่อยของรายการจากอาร์เรย์และส่งคืนเป็นอาร์เรย์ใหม่"

คุณมีสองตัวเลือกที่นี่:
1) ย้าย$scope.itemsไปที่อาร์เรย์หรือ -
2) กรองng-repeatรายการล่วงหน้าดังนี้:

<div ng-repeat="(k,v) in filterSecId(items)">
    {{k}} {{v.pos}}
</div>

และบนคอนโทรลเลอร์:

$scope.filterSecId = function(items) {
    var result = {};
    angular.forEach(items, function(value, key) {
        if (!value.hasOwnProperty('secId')) {
            result[key] = value;
        }
    });
    return result;
}

jsfiddle : http://jsfiddle.net/bmleite/WA2BE/


9
เราต้องระมัดระวังกับแนวทางนี้เพื่อหลีกเลี่ยงการวนซ้ำ (การย่อย) ที่ไม่มีที่สิ้นสุด ดู6054และ705 สรุปโดยNarretz : ในระยะสั้นการใช้ฟังก์ชันเพื่อส่งคืนคอลเล็กชันใน ng-repeat เป็นการต่อต้านรูปแบบ เป็นการดีกว่าที่จะกำหนดคอลเลกชันให้กับคุณสมบัติขอบเขตและวนซ้ำ
Joe23

3
ความคิดเห็นที่เป็นประโยชน์ นี่คือการขว้างฉันเป็นห่วง; ฉันคาดว่าจะสามารถกรองสิ่งที่ทำซ้ำได้ ขอบคุณมาก. :)
Chris Krycho

3
หมายเหตุ: นี่เป็นการต่อต้านรูปแบบที่สมบูรณ์แบบในขณะนี้ ตอนนี้ Angular 1.3 มีตัวกรองไร้สถานะ ( egghead.io/lessons/… ) ดังนั้นคุณจึงต้องการสร้างตัวกรองสำหรับสิ่งนี้
kentcdodds

8
@kentcdodds ไม่โพสต์ลิงค์ที่ไม่ฟรี!
Sebastian

11
ทำไมไม่เพิ่ม ng-if ในองค์ประกอบซ้ำ?
CarbonDry

45

วิธีแก้ปัญหาของฉันคือสร้างตัวกรองที่กำหนดเองและใช้:

app.filter('with', function() {
  return function(items, field) {
        var result = {};
        angular.forEach(items, function(value, key) {
            if (!value.hasOwnProperty(field)) {
                result[key] = value;
            }
        });
        return result;
    };
});

และใน html:

 <div ng-repeat="(k,v) in items | with:'secId'">
        {{k}} {{v.pos}}
 </div>

1
อย่างไรก็ตามมันจะวนซ้ำ n * n ครั้ง
maxisam

27

นอกจากนี้คุณสามารถใช้ng-repeatกับng-if:

<div ng-repeat="(key, value) in order" ng-if="value > 0">

2
ฉลาด. ซึ่งช่วยประหยัดเวลาได้มาก
Safwan


11

คุณสามารถใช้โมดูลangular.filterจากนั้นคุณสามารถกรองได้ตามคุณสมบัติที่ซ้อนกัน
ดู: jsbin
2 ตัวอย่าง:

JS:

angular.module('app', ['angular.filter'])
  .controller('MainCtrl', function($scope) {
  //your example data
  $scope.items = { 
    'A2F0C7':{ secId:'12345', pos:'a20' },
    'C8B3D1':{ pos:'b10' }
  };
  //more advantage example
  $scope.nestedItems = { 
    'A2F0C7':{
      details: { secId:'12345', pos:'a20' }
    },
    'C8B3D1':{
      details: { pos:'a20' }
    },
    'F5B3R1': { secId:'12345', pos:'a20' }
  };
});

HTML:

  <b>Example1:</b>
  <p ng-repeat="item in items | toArray: true | pick: 'secId'">
    {{ item.$key }}, {{ item }}
  </p>

  <b>Example2:</b>
  <p ng-repeat="item in nestedItems | toArray: true | pick: 'secId || details.secId' ">
    {{ item.$key }}, {{ item }}
  </p> 

21
คุณควรเปิดเผยว่านั่นangular.filterไม่ใช่โมดูลเชิงมุมหลักและคุณเป็นผู้เขียน
demisx

ดูเหมือนว่าtoArrayจะไม่มีตัวกรองอีกต่อไป มีการเปลี่ยนเนื่องจากfilterตัวกรองยังไม่อนุญาตให้ใช้วัตถุหรือไม่?
trysis

6

มันค่อนข้างช้า แต่ฉันมองหาตัวกรองที่คล้ายกันและสิ้นสุดโดยใช้สิ่งนี้:

<div ng-controller="TestCtrl">
 <div ng-repeat="(k,v) in items | filter:{secId: '!!'}">
   {{k}} {{v.pos}}
 </div>
</div>

2
คุณทำให้สิ่งนี้ทำงานได้อย่างไร? เมื่อฉันใช้ตัวกรองกับวัตถุที่ทำซ้ำฉันได้รับข้อผิดพลาดซึ่งเป็นสิ่งที่คาดว่าจะได้รับจากเอกสาร Angular
tonestrike

1

แม้ว่าคำถามนี้จะค่อนข้างเก่า แต่ฉันก็อยากแบ่งปันวิธีแก้ปัญหาสำหรับนักพัฒนาเชิงมุม 1 ประเด็นคือแค่นำตัวกรองเชิงมุมเดิมมาใช้ซ้ำ แต่ส่งผ่านวัตถุใด ๆ เป็นอาร์เรย์อย่างโปร่งใส

app.filter('objectFilter', function ($filter) {
    return function (items, searchToken) {
        // use the original input
        var subject = items;

        if (typeof(items) == 'object' && !Array.isArray(items)) {
            // or use a wrapper array, if we have an object
            subject = [];

            for (var i in items) {
                subject.push(items[i]);
            }
        }

        // finally, apply the original angular filter
        return $filter('filter')(subject, searchToken);
    }
});

ใช้แบบนี้:

<div>
    <input ng-model="search" />
</div>
<div ng-repeat="item in test | objectFilter : search">
    {{item | json}}
</div>

นี่คือผู้ทำลายล้าง


0

ฉันได้สร้างตัวกรองทั่วไปอีกเล็กน้อยที่ฉันเคยใช้ในหลายโครงการแล้ว:

  • object = อ็อบเจ็กต์ที่ต้องการกรอง
  • ฟิลด์ = ฟิลด์ภายในวัตถุที่เราจะกรอง
  • filter = ค่าของตัวกรองที่ต้องตรงกับฟิลด์

HTML:

<input ng-model="customerNameFilter" />
<div ng-repeat="(key, value) in filter(customers, 'customerName', customerNameFilter" >
   <p>Number: {{value.customerNo}}</p>
   <p>Name: {{value.customerName}}</p>
</div>

JS:

  $scope.filter = function(object, field, filter) {
    if (!object) return {};
    if (!filter) return object;

    var filteredObject = {};
    Object.keys(object).forEach(function(key) {
      if (object[key][field] === filter) {
        filteredObject[key] = object[key];
      }
    });

    return filteredObject;
  };
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.