Search code examples
javascriptangularjsjsonsortingangularjs-orderby

Custom sorting of objects by key in ng-repeat


I have an object stored in $scope.addresscards inside a controller. The js is given below:

var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
  $scope.addresscards = {
      "work_address": {
          "location":"workLoc",
          "address": "workAddr",
          "flat_no": "worknumber",
          "landmark": "workLandmark"
      },
      "random1_address": {
          "location":"someLoc",
          "address": "SomeAddr",
          "flat_no": "Somenumber",
          "landmark": "someLandmark"
      },
      "home_address": {
          "location":"homeLoc",
          "address": "homeAddr",
          "flat_no": "homenumber",
          "landmark": "homeLandmark"
      },
      "random2_address": {
          "location":"someLoc2",
          "address": "SomeAddr2",
          "flat_no": "Somenumber2",
          "landmark": "someLandmark2"
      }
  };
}

I'm using ng-repeat to display the addresses. Here is the HTML:

<div ng-controller="MyCtrl">
  <ul ng-repeat="(addressKey,addressVal) in addresscards">
     <li>{{addressKey}} has :: {{addressVal.location}},{{addressVal.address}}, {{addressVal.location}}, {{addressVal.address}}</li>
  </ul>
</div>

My output is:

home_address has :: homeLoc, homeAddr, homeLoc, homeAddr
random1_address has :: someLoc, SomeAddr, someLoc, SomeAddr
random2_address has :: someLoc2, SomeAddr2, someLoc2, SomeAddr2
work_address has :: workLoc, workAddr, workLoc, workAddr

I want to display the output such that, if the object has home_address it should be displayed 1st, then if the object has work_address it should be displayed. Then rest of the object should be showed alphabetically.

Here is expected result that I want to display:

home_address has :: homeLoc, homeAddr, homeLoc, homeAddr
work_address has :: workLoc, workAddr, workLoc, workAddr
random1_address has :: someLoc, SomeAddr, someLoc, SomeAddr
random2_address has :: someLoc2, SomeAddr2, someLoc2, SomeAddr2

I tried it using orderBy, It doesn't work on objects. How do I achieve this?


Solution

  • You can add a property to your address objects

    $scope.addresscards = {
          "work_address": {
              "location":"workLoc",
              "address": "workAddr",
              "flat_no": "worknumber",
              "landmark": "workLandmark",
              "sort" : "2"
          },
          "random1_address": {
              "location":"someLoc",
              "address": "SomeAddr",
              "flat_no": "Somenumber",
              "landmark": "someLandmark"
          },
          "home_address": {
              "location":"homeLoc",
              "address": "homeAddr",
              "flat_no": "homenumber",
              "landmark": "homeLandmark",
              "sort" : "1"
          },
          "random2_address": {
              "location":"someLoc2",
              "address": "SomeAddr2",
              "flat_no": "Somenumber2",
              "landmark": "someLandmark2"
          }
      };
    

    and in your ng-repeat you can orderBy multiple fields first by sort to display home and work address first and then by address key for alphabetical order.

      <ul ng-repeat="(addressKey,addressVal) in addresscards | orderBy:['sort','addressKey']">
         <li>{{addressKey}} has :: {{addressVal.location}},{{addressVal.address}}, {{addressVal.location}}, {{addressVal.address}}</li>
      </ul>
    

    or in your controller you can sort all other addresses and append home and work address to the beginning of your list.

    Plunker