संपत्ति द्वारा छँटाई AngularJS


93

मैं जो करने की कोशिश कर रहा हूं वह संपत्ति के कुछ डेटा को सॉर्ट करना है। यहाँ उदाहरण है कि मुझे काम करना चाहिए था लेकिन ऐसा नहीं हुआ।

HTML हिस्सा:

<div ng-app='myApp'>
    <div ng-controller="controller">
    <ul>
        <li ng-repeat="(key, value) in testData | orderBy:'value.order'">
            {{value.order}}. {{key}} -> {{value.name}}
        </li>
    </ul>
    </div>
</div>

जेएस भाग:

var myApp = angular.module('myApp', []);

myApp.controller('controller', ['$scope', function ($scope) {

    $scope.testData = {
        C: {name:"CData", order: 1},
        B: {name:"BData", order: 2},
        A: {name:"AData", order: 3},
    }

}]);

और परिणाम:

  1. ए -> एडाटा
  2. बी -> बीडाटा
  3. सी -> सीडीटा

... कि IMHO इस तरह दिखना चाहिए:

  1. सी -> सीडीटा
  2. बी -> बीडाटा
  3. ए -> एडाटा

क्या मुझे कुछ याद आया (यहाँ प्रयोग करने के लिए JSFiddle तैयार है )?

जवाबों:


148

AngularJS 'ऑर्डरबाय फिल्टर सिर्फ सरणियों का समर्थन करता है - कोई वस्तु नहीं। तो आपको एक छोटा सा फ़िल्टर लिखना होगा, जो आपके लिए छँटाई करे।

या आपके द्वारा हैंडल किए जाने वाले डेटा का प्रारूप बदलें (यदि आपका उस पर प्रभाव है)। एक सरणी जिसमें ऑब्जेक्ट्स होते हैं, वे देशी ऑर्डरबाय फ़िल्टर द्वारा छांटे जाते हैं।

यहाँ मेरी है orderObjectBy AngularJS के लिए फिल्टर:

app.filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });
    return array;
 }
});

आपके विचार में उपयोग:

<div class="item" ng-repeat="item in items | orderObjectBy:'position'">
    //...
</div>

ऑब्जेक्ट को इस उदाहरण में एक स्थिति विशेषता की आवश्यकता है, लेकिन आपके पास ऑब्जेक्ट्स में किसी भी विशेषता का उपयोग करने के लिए लचीलापन है (पूर्णांक युक्त), केवल दृश्य में परिभाषा द्वारा।

उदाहरण JSON:

{
    "123": {"name": "Test B", "position": "2"},
    "456": {"name": "Test A", "position": "1"}
}

यहाँ एक फिडेल है जो आपको उपयोग दिखाता है: http://jsfiddle.net/4tkj8/1/


1
यह भी खूब रही। मैंने asc / desc को सॉर्ट करने का विकल्प जोड़ा: app.filter ('orderObjectBy', function () {रिटर्न फंक्शन (इनपुट, एट्रिब्यूट, डायरेक्शन) {if ((angular.isObject (इनपुट)) रिटर्न इनपुट; var array = [] ; (इनपुट में var objectKey) {array.push (इनपुट [objectKey]);} array.sort (फंक्शन (a, b) {a = parseInt (एक [विशेषता]); b = parseInt (b [विशेषता]); ; वापसी दिशा == 'asc'? - (a: b: b - a;}); return array;}}}; HTML में: <tr ng-repeat = "val in list | orderObjectBy: 'Prop': 'asc'">
Jazzy

@ अगर यह सरणी की तरह वस्तु है तो क्या होगा? यानी{1:'Example 1', 2:'Example 2', 3:'Example 3', ...}
यूजीन

8
महान जवाब लेकिन हमने इस तरह से वस्तु की कुंजी खो दी है। इसे रखने के लिए, बस इसे फ़िल्टर में नई सरणी की पंक्तियों को जोड़ दें जैसे for(var objectKey in input) { input[objectKey]['_key'] = objectKey; array.push(input[objectKey]); }कि हम उपयोग कर सकते हैं<div ng-repeat="value in object | orderObjectBy:'order'" ng-init="key = value['_key']">
निकोलस जैनेल

7
यह ध्यान देने योग्य है कि Angular.js वस्तुओं के एक सरणी में अब एक संपत्ति द्वारा छँटाई का समर्थन करता है... | orderBy: 'name' :।
वाइल्डहनी

2
@Wildhoney यह प्रश्न ऑब्जेक्ट के साथ ऑब्जेक्ट्स को ऑर्डर करने के बारे में है, न कि ऑब्जेक्ट्स वाले सरणियों को।
अर्मिन

31

यह बहुत आसान है, बस इसे इस तरह से करें

$scope.props = [{order:"1"},{order:"5"},{order:"2"}]

ng-repeat="prop in props | orderBy:'order'"

33
यह साहचर्य सरणियों के लिए काम नहीं करता है, जो कि प्रश्न के बारे में है।
एमएफबी

7

मत भूलो कि parseInt () केवल पूर्णांक मूल्यों के लिए काम करता है। स्ट्रिंग मानों को क्रमबद्ध करने के लिए आपको इसे स्वैप करना होगा:

array.sort(function(a, b){
  a = parseInt(a[attribute]);
  b = parseInt(b[attribute]);
  return a - b;
});

इसके साथ:

array.sort(function(a, b){
  var alc = a[attribute].toLowerCase(),
      blc = b[attribute].toLowerCase();
  return alc > blc ? 1 : alc < blc ? -1 : 0;
});

6

जैसा कि आप कोणीय-JS ( https://github.com/angular/angular.js/blob/master/src/ng/filter/orderBy.js ) के कोड में देख सकते हैं कि एनजी-रिपीट वस्तुओं के लिए काम नहीं करता है। यहाँ एक हैक है सॉर्टफंक्शन के साथ।

http://jsfiddle.net/sunnycpp/qaK56/33/

<div ng-app='myApp'>
    <div ng-controller="controller">
    <ul>
        <li ng-repeat="test in testData | orderBy:sortMe()">
            Order = {{test.value.order}} -> Key={{test.key}} Name=:{{test.value.name}}
        </li>
    </ul>
    </div>
</div>

myApp.controller('controller', ['$scope', function ($scope) {

    var testData = {
        a:{name:"CData", order: 2},
        b:{name:"AData", order: 3},
        c:{name:"BData", order: 1}
    };
    $scope.testData = _.map(testData, function(vValue, vKey) {
        return { key:vKey, value:vValue };
    }) ;
    $scope.sortMe = function() {
        return function(object) {
            return object.value.order;
        }
    }
}]);

4

http://docs.angularjs.org/api/ng.filter:orderBy के अनुसार , ऑर्डर एक सरणी को सॉर्ट करता है। आपके मामले में आप एक ऑब्जेक्ट पास कर रहे हैं, इसलिए आपको अपना स्वयं का छँटाई समारोह लागू करना होगा।

या एक सरणी पास करें -

$scope.testData = {
    C: {name:"CData", order: 1},
    B: {name:"BData", order: 2},
    A: {name:"AData", order: 3},
}

http://jsfiddle.net/qaK56/ पर एक नज़र डालें


मुझे पता है कि यह सरणियों के साथ काम करता है .. तो इसका समाधान मेरे स्वयं के छँटाई समारोह को लिखना है?
प्रिमोसक

आपका jsfiddle! = आपका कोड यू पोस्ट किया गया। यह आपके उदाहरण के लिए यहाँ सही jsfiddle है: jsfiddle.net/qaK56/92
mrzmyr

3

आपको अपनी समस्या को ठीक करने के लिए अपनी JSON संरचना में वास्तव में सुधार करना चाहिए:

$scope.testData = [
   {name:"CData", order: 1},
   {name:"BData", order: 2},
   {name:"AData", order: 3},
]

तब आप कर सकते थे

<li ng-repeat="test in testData | orderBy:order">...</li>

मुझे लगता है कि समस्या यह है कि (कुंजी, मूल्य) चर ऑर्डरबाय फ़िल्टर के लिए उपलब्ध नहीं हैं, और आपको अपनी कुंजी में डेटा संग्रहीत नहीं करना चाहिए


2
बता दें कि Firebase;)
MFB

जहाँ तक मुझे पता है, आप डेटा को
फायरबेस

यदि आप फायरबेस में एक सरणी स्टोर करते हैं, तो यह सरणी के लिए कुंजी के रूप में एक यूआईडी का उपयोग करता है। ऐसी कई स्थितियाँ हैं जहाँ किसी को डेटा संरचना पर नियंत्रण नहीं मिलता है, इसलिए आपका सुझाव थोड़ा व्यापक हो सकता है।
एमएफबी

क्या की एक सरणी स्टोर? डेटा संरचना पर हमेशा नियंत्रण होता है। साथ ही ओपी ने फायरबेस के बारे में कुछ नहीं बताया।
जोशुआ वोवार्ड

2

यहाँ मैं क्या किया है और यह काम करता है।
मैंने सिर्फ एक कठोर वस्तु का उपयोग किया है।

$scope.thread = [ 
  {
    mostRecent:{text:'hello world',timeStamp:12345678 } 
    allMessages:[]
  }
  {MoreThreads...}
  {etc....}
]

<div ng-repeat="message in thread | orderBy : '-mostRecent.timeStamp'" >

अगर मैं पाठ द्वारा सॉर्ट करना चाहता था तो मैं करूँगा

orderBy : 'mostRecent.text'

2

मैं फ़िल्टर के अपने उन्नत संस्करण को जोड़ूंगा जो अगले सिंटैक्स का समर्थन करने में सक्षम है:

ng-repeat="(id, item) in $ctrl.modelData | orderObjectBy:'itemProperty.someOrder':'asc'

app.filter('orderObjectBy', function(){

         function byString(o, s) {
            s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
            s = s.replace(/^\./, '');           // strip a leading dot
            var a = s.split('.');
            for (var i = 0, n = a.length; i < n; ++i) {
                var k = a[i];
                if (k in o) {
                    o = o[k];
                } else {
                    return;
                }
            }
            return o;
        }

        return function(input, attribute, direction) {
            if (!angular.isObject(input)) return input;

            var array = [];
            for(var objectKey in input) {
                if (input.hasOwnProperty(objectKey)) {
                    array.push(input[objectKey]);
                }
            }

            array.sort(function(a, b){
                a = parseInt(byString(a, attribute));
                b = parseInt(byString(b, attribute));
                return direction == 'asc' ? a - b : b - a;
            });
            return array;
        }
    })

इस धागे में उनके जवाब के लिए आर्मिन और जेसन का धन्यवाद, और इस धागे में अलनीतक ।


1

अर्मिन का उत्तर + वस्तु प्रकार और गैर-कोणीय कुंजी जैसे के लिए एक सख्त जाँच $resolve

app.filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
      if (typeof(input[objectKey])  === "object" && objectKey.charAt(0) !== "$")
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });

    return array;
 }
})

1

निम्नलिखित ऑब्जेक्ट द्वारा कुंजी के ऑब्जेक्ट के आदेश के लिए या किसी ऑब्जेक्ट के भीतर कुंजी के द्वारा अनुमति देता है ।

टेम्पलेट में आप कुछ ऐसा कर सकते हैं:

    <li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someKey'">

या और भी:

    <li ng-repeat="(k,i) in objectList | orderObjectsBy: 'someObj.someKey'">

फ़िल्टर:

app.filter('orderObjectsBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    // Filter out angular objects.
    var array = [];
    for(var objectKey in input) {
      if (typeof(input[objectKey])  === "object" && objectKey.charAt(0) !== "$")
        array.push(input[objectKey]);
    }

    var attributeChain = attribute.split(".");

    array.sort(function(a, b){

      for (var i=0; i < attributeChain.length; i++) {
        a = (typeof(a) === "object") && a.hasOwnProperty( attributeChain[i]) ? a[attributeChain[i]] : 0;
        b = (typeof(b) === "object") && b.hasOwnProperty( attributeChain[i]) ? b[attributeChain[i]] : 0;
      }

      return parseInt(a) - parseInt(b);
    });

    return array;
 }
})

क्या यह सामान्य है कि ऑब्जेक्टलिस्ट में (k, i) की चाबियाँ 0 और 1 के में बदल जाती हैं?
केन वर्नैलेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.