0

I'm relatively new to Angular 2 and I need to sort/group an array of objects based on the first letter of their name. eg.:

{
   "type": "fruit",
   "name": "apple",
},
{
   "type": "fruit",
   "name": "banana",
},
{
   "type": "vegetable",
   "name": "broccoli",
},
{
   "type": "fruit",
   "name": "orange",
},

I would like it to show it like:

<h3>A</h3>
<ul>
    <li>apple</li>
</ul>
<h3>B</h3>
<ul>
    <li>banana</li>
    <li>broccoli</li>
</ul>
<h3>O</h3>
<ul>
    <li>orange</li>
</ul>

I found this post: How to group data in Angular 2 ?.

I tried it like:

<div *ngFor="let item of food | groupBy:'name.charAt(0)'">
  <h3>{{name.charAt(0) | uppercase}}</h3>
  <li>...</li> 
</div>

I know i probably need a pipe, but i cant get it to work.

Hope someone can help

Community
  • 1
  • 1
Sephen
  • 1,111
  • 3
  • 16
  • 38

3 Answers3

0

Hi have you tried maybe somthing like:

import { Pipe, PipeTransform } from '@angular/core';
/*
 * Raise the value exponentially
 * Takes an exponent argument that defaults to 1.
 * Usage:
 *   value | firstLetter:'a'
 * Example:
 *   {{ 'banana' |  firstLetter:'b'}}
 *  
*/
@Pipe({ name: 'firstLetter' })
export class ExponentialStrengthPipe implements PipeTransform {
    transform(value: string, letter: string): string {
        if (!value || !letter) return value;
        return value.charAt(0).indexOf(letter) > -1 ? value : "";
    }
}

Maybe you can put more check on string value if as more than 1 char etc ..i just put an idea of custom pipe .. hope it help you

federico scamuzzi
  • 3,708
  • 1
  • 17
  • 24
0

if you don't want to use pipe then you can use lodash for changing order of your array of objects.

_.sortBy(collection, [iteratees=[_.identity]])

Creates an array of elements, sorted in ascending order by the results of running each element in a collection thru each iteratee. This method performs a stable sort, that is, it preserves the original sort order of equal elements. The iteratees are invoked with one argument: (value).

Arguments

collection (Array|Object): The collection to iterate over. [iteratees=[_.identity]] (...(Function|Function[])): The iteratees to sort by.

Returns

(Array): Returns the new sorted array.

Example

var users = [
  { 'user': 'fred',   'age': 48 },
  { 'user': 'barney', 'age': 36 },
  { 'user': 'fred',   'age': 40 },
  { 'user': 'barney', 'age': 34 }
];

_.sortBy(users, [function(o) { return o.user; }]);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]

_.sortBy(users, ['user', 'age']);
// => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
Amit kumar
  • 6,029
  • 6
  • 30
  • 40
0

You can use this Pipe that groups the input array by the first letter:

@Pipe({
  name: 'firstLetterGroupBy'
})
export class FirstLetterGroupBy implements PipeTransform {

  transform(input: any, prop: string): Array<any> {

    if (!isArray(input)) {
      return input;
    }

    const arr: { [key: string]: Array<any> } = {};

    for (const value of input) {
      const field: any = getProperty(value, prop);

      const firstLetter = field.charAt(0).toUpperCase();

      if (isUndefined(arr[firstLetter])) {
        arr[firstLetter] = [];
      }

      arr[firstLetter].push(value);
    }

    return Object.keys(arr).map(key => ({ key, 'value': arr[key] }));
  }
}

and then:

<div *ngFor="let item of yourArray | firstLetterGroupBy:'name'">
   <span>{{item.key}}</span>
   <ul>
       <li *ngFor="let v of item.value">
       {{v.name}}
       <hr>
       </li>
   </ul>
</div>

Stack Diego
  • 1,309
  • 17
  • 43