2012-12-14 20 views
24

में सरणी के बजाय ऑब्जेक्ट मानचित्र पर फ़िल्टर करना एक $ स्कोप प्रॉपर्टी के साथ नियंत्रक को देखते हुए जो नीचे की तरह सरणी के बजाय अन्य गुणों वाला ऑब्जेक्ट है, मुझे ng-repeat सेट को कैसे फ़िल्टर करना चाहिए?AngularJS

यहाँ एक JSFiddle है: http://jsfiddle.net/ZfGx4/110/

नियंत्रक:

function HelloCntl($scope, $filter) { 
    $scope.friends = { 
     john: { 
      name: 'John', 
      phone: '555-1276' 
     }, 
     mary: { 
      name: 'Mary', 
      phone: '800-BIG-MARY' 
     }, 
     mike: { 
      name: 'Mike', 
      phone: '555-4321' 
     }, 
     adam: { 
      name: 'Adam', 
      phone: '555-5678' 
     }, 
     julie: { 
      name: 'Julie', 
      phone: '555-8765' 
     } 
    }; 
}​ 

टेम्पलेट:

<div ng:app> 
<div ng-controller="HelloCntl"> 
    <input placeholder="Type to filter" ng-model="query">  
    <ul> 
    <li ng-repeat="(id, friend) in friends | filter:query"> 
    <span>{{friend.name}} @ {{friend.phone}}</span> 
    </li> 
    </ul> 
</div> 
</div> 
+2

Jsfiddle की ng-if नहीं रह गया है – Jackie

उत्तर

26

मैं अपनी डेटा संरचना को सरणी में बदल दूंगा। वैसे भी, यहां अपने दोस्तों के ऑब्जेक्ट को फ़िल्टर करने के लिए एक और कार्यान्वयन है।

angular.module('filters',['utils']) 
    .filter('friendFilter', function(utils){ 

    return function(input, query){ 
     if(!query) return input; 
     var result = []; 

     angular.forEach(input, function(friend){ 
     if(utils.compareStr(friend.name, query) || 
      utils.compareStr(friend.phone, query)) 
      result.push(friend);   
     }); 
     return result; 
    }; 
    }); 

केवल एक बार वस्तु पर यह दोहराता, name और phone से तुलना करता है और इस तरह कहा जा सकता है।

<li ng-repeat="friend in friends | friendFilter:query"> 

मैं एक मॉड्यूल में compareStr परिभाषित है, लेकिन क्या तुम सच में ऐसा करने की जरूरत नहीं है।

angular.module('utils', []) 
    .factory('utils', function(){ 
    return{ 
     compareStr: function(stra, strb){ 
     stra = ("" + stra).toLowerCase(); 
     strb = ("" + strb).toLowerCase(); 
     return stra.indexOf(strb) !== -1; 
     } 
    }; 
    }); 

मत भूलना अपने ऐप्लिकेशन में filters मॉड्यूल सुई

angular.module('app',['filters']) 

यहाँ पूर्ण उदाहरण है: http://jsbin.com/acagag/5/edit

+0

ग्रेट समाधान, धन्यवाद! –

13

मुझे लगता है कि आप इसे सीधे नहीं कर सकते 'फिल्टर' के साथ।

function filterFilter() { 
    return function(array, expression) { 
    if (!(array instanceof Array)) return array; 

तो अगर यह एक सरणी से कुछ अलग प्राप्त करता है, यह कुछ भी नहीं करता है: Angular.js में कोड को देखते हुए, इन फिल्टर समारोह के पहले लाइनें हैं।

यहाँ एक तरह से यह करने के लिए यकीन नहीं अगर मैं इसे की सिफारिश करेंगे है, है, लेकिन यह एक विचार है है:,

नियंत्रक में बस इसे फिल्टर करने के लिए पारित करने से पहले एक सरणी में बदलने का:

$scope.filteredFriends = function() { 
    var array = []; 
    for(key in $scope.friends) { 
     array.push($scope.friends[key]); 
    } 
    return $filter('filter')(array, $scope.query); 
} 

और एनजी-दोहराने:

<li ng-repeat="friend in filteredFriends()"> 

उदाहरण: http://jsbin.com/acagag/2/edit

शायद एक बेहतर समाधान एक कस्टम फ़िल्टर लिखना है।

+0

मैं 'filter' फिल्टर की आवश्यकता सरणियों पता था कि काम करता है, लेकिन मैं नहीं था यह नहीं पता कि उन्होंने 'सरणी का उदाहरण' इस्तेमाल किया है ताकि यह जांच सके कि कुछ सरणी थी या नहीं! मैं एक अलग तरह की जांच की उम्मीद करूँगा (http://perfectionkills.com/instanceof-cononsidered-harmful-or-how-to-write-a-robust-isarray/)। वैसे भी, मैंने आपके उदाहरण के लिए आधार के रूप में अपना उदाहरण लिया। क्यों कहने के लिए – jaime

+0

+1! धन्यवाद। – JnBrymn

1

मैं कैसे किसी सरणी के लिए अपने ऑब्जेक्ट नहीं बदलने के लिए एक उदाहरण बना दिया । मुझे लगता है कि यह सवाल अधिक सही जवाब देता है।

मुझे वही समस्या थी जो मैं किसी ऑब्जेक्ट में नहीं खोज सका।

http://jsbin.com/acagag/223/edit

angular.module('filters',['utils']) 
    .filter('friendFilter', function(utils){ 

    return function(input, query){ 
     if(!query) return input; 
     var result = {}; 

     angular.forEach(input, function(friendData, friend){ 
     if(utils.compareStr(friend, query) || 
      utils.compareStr(friendData.phone, query)) 
      result[friend] = friendData;   
     }); 
     return result; 
    }; 
    }); 

तो बस के बजाय एक सरणी लौटने आप एक वस्तु लौट आते हैं।

उम्मीद है कि यह किसी की मदद करेगा!

0

के बजाय एक फिल्टर कर सकते हैं भी बस का उपयोग कर आप:

$http.get('api/users').success(function(data){ 
    angular.forEach(data, function(value, key){ 
     users.push(value); 
    }); 
    $scope.users = users; 
}); 

और टेम्पलेट

<input type="text" ng-model="query" placeholder="Search user"/> 

<li ng-repeat="user in users | filter:query"> 
    {{ user.name }} 
</li> 
3

मैं एक ही समस्या थी, और अपने ही फिल्टर है कि एक नक्शा स्वीकार करता है बनाने द्वारा सफल हो गया है, जबकि वास्तविक मिलान करने के लिए अभी भी अंतर्निर्मित फ़िल्टर का उपयोग कर रहे हैं।

मेरा कस्टम फ़िल्टर मानचित्र को पार करता है, और प्रत्येक तत्व के लिए अंतर्निर्मित फ़िल्टर को कॉल करता है, लेकिन यह देखते हुए कि फ़िल्टर केवल एक सरणी स्वीकार करता है, मैं प्रत्येक तत्व को लंबाई 1 (नीचे [डेटा]) की सरणी में लपेटता हूं। तो मैच सफल होता है उत्पादन सरणी की दूरी अभी भी 1.

.filter('mapFilter', function($filter) { 
    var filter = $filter('filter'); 

    return function(map, expression, comparator) { 
    if (! expression) return map; 

    var result = {}; 
    angular.forEach(map, function(data, index) { 
     if (filter([data], expression, comparator).length) 
     result[index] = data;   
    }); 

    return result; 
    } 
}) 

है इस सेटअप निश्चित रूप से दक्षता खो देता है क्योंकि निर्मित फिल्टर यह नक्शे में प्रत्येक तत्व के लिए क्या करने की जरूरत निर्धारित करने के लिए आवश्यक है, बजाय है केवल एक बार यदि आप इसे सभी तत्वों के साथ एक सरणी देते हैं, लेकिन मेरे मामले में, 500 तत्वों के मानचित्र के साथ फ़िल्टरिंग अभी भी अनावश्यक है।

+0

यह बहुत अच्छा काम करता है। धन्यवाद –

1

नहीं सर्वोत्कृष्ट समाधान लेकिन आप कुछ त्वरित और गंदी चाहते हैं:

<li ng-repeat="(id, friend) in friends | filter:query" ng-hide="id !== query.id"> 
    <span>{{friend.name}} @ {{friend.phone}}</span> 
</li> 

या बजाय ng-hide