0

I grouped a data array using lodash and can see the output in my console, but my *ngFor loops don't display the data on my html page. Can anyone point out what I'm missing here?

app.component.ts:

export class AppComponent {
  name = "Angular";

  data = [
    {
      customer: {
        name: "John"
      },
      transaction_date: "2017-04-18"
    },
    {
      customer: {
        name: "Dick"
      },
      transaction_date: "2017-06-30"
    },
    {
      customer: {
        name: "Harry"
      },
      transaction_date: "2017-04-03"
    },
    {
      customer: {
        name: "John"
      },
      transaction_date: "2017-05-03"
    }
  ];

  constructor() {}

  ngOnInit() {
    // Sort by Month

    // Format month
    const monthName = item =>
      moment(item.transaction_date, "YYYY-MM-DD").format("MMM");

// Establish groupBy array
    const byMonth = _.chain(this.data)
      .groupBy(monthName)
      .mapValues(items => _.map(items, "customer.name"))
      .value();
    console.log(byMonth);
    return byMonth;
    console.log(monthName);

    // By Day
    const dayName = item =>
      moment(item.transaction_date, "YYYY-MM-DD").format("DD");

    const byDay = _.chain(this.data)
      .groupBy(dayName)
      .mapValues(items => _.map(items, "customer.name"))
      .value();
    console.log(byDay);
    return byDay;
  }
}

app.component.html

<table *ngFor="let month of months">
    <tr>
        <th>{{month.month}}</th>
    </tr>
    <tr>
        <td>
            <table *ngFor="let customer of customers">
                <tr>
                    <td>
                        {{customer.name}}
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>

Desired HTML Format (in a table but the formatting wasn't supported):

  • April
    • John
    • Harry
  • May
    • Dick
  • June
    • John

Thanks guys! :)

5
  • 3
    You're not defining customers in your component controller, and the correct syntax is *ngFor="let customer of customers". I imagine you have some errors in the console. Commented Feb 27, 2020 at 20:01
  • 2
    Maybe I'm missing something, but it looks like the only fields existing outside of ngOnInit() are name and data. So I don't think you'd be able to iterate over months or customers with an *ngFor. Commented Feb 27, 2020 at 20:02
  • i fixed the ngfor loop but it's still not displaying the table Commented Feb 27, 2020 at 20:14
  • if the 'data' equals to your 'customers'? looking at the format, your name is inside customer object, when loop, it should be like let customer of customers.... {{ customer.customer.name }}, and for the date, {{ customer.transaction_date }} Commented Feb 27, 2020 at 20:17
  • OKay, ive remade my problem here, could you take a look? stackblitz.com/edit/angular-dkpyvp Commented Feb 27, 2020 at 20:30

1 Answer 1

1

There are a few mistakes, but you're close.

1) You need to declare a public property in your component that will be used to loop through. Notice how I created public myData.

2) You then need to initialize that object with the data you want to display. In your original code you were trying to do a return from the ngOnInit. That is not what you want to do. You want to assign that data to your public property myData

3) You have to recognize Angular ngFor does not want to loop through anything that is not an array by default. Lucky for you since Angular version 6 they provided support to loop over objects. However, in order to accomplish that you need to include the new pipe | keyvalue.

Working StackBlitz Demo

export class AppComponent {
  name = "Angular";

  public myData = {};

  data = [
    {
      customer: {
        name: "John"
      },
      transaction_date: "2017-04-18"
    },
    {
      customer: {
        name: "Dick"
      },
      transaction_date: "2017-06-30"
    },
    {
      customer: {
        name: "Harry"
      },
      transaction_date: "2017-04-03"
    },
    {
      customer: {
        name: "John"
      },
      transaction_date: "2017-05-03"
    }
  ];

  constructor() {}

  ngOnInit() {
    // Sort by Month

    // Format month
    const monthName = item =>
      moment(item.transaction_date, "YYYY-MM-DD").format("MMM");

    // Establish groupBy array
    this.myData = _.chain(this.data)
      .groupBy(monthName)
      .mapValues(items => _.map(items, "customer.name"))
      .value();
    console.log(this.myData);
  }
}

HTML

<table *ngFor="let data of myData | keyvalue">
    <tr>
        <th>{{data.key}}</th>
    </tr>
    <tr>
        <td>
            <table *ngFor="let customer of data.value">
                <tr>
                    <td>
                        {{customer}}
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>
Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant! Thank you so much! It looks like my main issue was I never declared the public property. I'm very new to Angular so I still have quite a bit to learn, thank you again! :D

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.