1

I am new to Angular JS and know basic functionality. I am struggling to use ng-repeat and filter options to get the desired output by non unique keys.

I would like to show the cars in html by color or make categories. so desired result I would like to see is(in this case Color is selected):

Sort by: CarID, Make or **Color**
Blue
  Focus
Red
  Camry
  Mustang
Yellow
  LandCruiser

The arrays coming from controller are:

 cars: [
{
    "carid": 1,
    "makeid": 1,
    "carname": 'camry',
    "color": 'red'
},
{
    "carid": 2,
    "makeid": 2,
    "carname": 'mustang',
    "color": 'red'
},
{
    "carid": 3,
    "makeid": 1,
    "carname": 'landcruiser',
    "color": 'yellow'
},
{
    "carid": 4,
    "makeid": 1,
    "carname": 'focus',
    "color": 'blue'
},
{
    "carid": 5,
    "makeid": 3,
    "carname": 'civic',
    "color": 'blue'


   }
] 

make: [
    {
        "makeid": 1,
        "makeName": 'Toyota'
    },
    {
        "makeid": 2,
        "makeName": 'Ford'
    },
    {
        "makeid": 3,
        "makeName": 'Civic'
    }
]

I tried to use following html but to no work

<div class="car" ng-repeat="car in cars track by color">
   <label>{{car.color}}</label>
   <div class="subcar" ng-repeat="c in cars filer by car.color">
      <label>{{c.carname}}</label>
   </div>
</div>

Also with above query, how do I replace color in filter with Make once user click on Make link?

hss
  • 317
  • 1
  • 2
  • 13
  • `filer by car.color`? Where are the docs for that format? – Patrick Apr 14 '16 at 20:07
  • maybe see this http://stackoverflow.com/questions/14733136/ng-repeat-filter-by-single-field and the filter page https://docs.angularjs.org/api/ng/filter/filter on how to apply filter. Instead of the input element you can also use a button, a dropdown menu,... – ralf htp Apr 14 '16 at 20:23

1 Answers1

1

You could utilize the angular filter module and the groupBy collection to achieve what you are after:

<div ng-app="myApp">
  <div ng-controller="myCtrl">
    <a href="" ng-click="ourGrouper ='color'">Color</a>
    <a href="" ng-click="ourGrouper ='makeid'">Make</a>

    <ul ng-repeat="(key, value) in cars | groupBy:ourGrouper">
      <li>
        <span ng-if="ourGrouper=='makeid'">{{(make | filter:{makeid:key})[0].makeName}}</span>
        <span ng-if="ourGrouper=='color'">{{key}}</span>
        <ul>
          <li ng-repeat="car in value">
            {{car.carname}}
          </li>
        </ul>
      </li>
    </ul>
  </div>
</div>

This works based upon your provided arrays of objects but truly isn't ideal... JSON isn't really designed to reference other objects by id, the setup you have above is more of a structure you would use to normalize an SQL database. If you have any control over these JSON objects, combine the two so the makeName replaces the makeid.

Something like:

$scope.cars = [{
    "carid": 1,
    "makeName": 'Toyota',
    "carname": 'camry',
    "color": 'red'
}];

And then you could remove the ng-if conditional logic in the ng-repeat and just put {{key}}

Working example: https://jsfiddle.net/r0m4n/pn0g3rrg/

Reference to docs for the module: https://github.com/a8m/angular-filter#groupby

r0m4n
  • 3,474
  • 3
  • 34
  • 43
  • Thank you. this works very well. I will look into changing the data structure as well. – hss Apr 15 '16 at 13:16
  • I had one more question, If I hhad to add "all Cars" as option. the how the grouper will behave? all cars and then in span: {{key}} – hss Apr 15 '16 at 14:22
  • @hss you should be ok, you can just setup your styles a little differently and pass an empty string to the grouper like this: https://jsfiddle.net/r0m4n/pn0g3rrg/1/ – r0m4n Apr 15 '16 at 16:17