1

In my Angular project, I'm trying to use *ngFor to display a calendar.

I have my months and the number of days in each, in an array of objects:

  public months: Array<Object> = [
    { month: "January", days: 31 },
    { month: "February", days: 28 },
    { month: "March", days: 31 },
    { month: "April", days: 30 },
    { month: "May", days: 31 },
    { month: "June", days: 30 },
    { month: "July", days: 31 },
    { month: "August", days: 31 },
    { month: "September", days: 30 },
    { month: "October", days: 31 },
    { month: "November", days: 30 },
    { month: "December", days: 31 },
  ];

and then I'm trying to display them using *ngFor. The months display correctly, but I can't quite figure out how to display each of the days correctly. Here's what I have for my html:

<div class="year" style="width: 100%; margin-top: 10px;">
  <h1 style="text-align: center; font-weight: 500;">2019 Vacation Calendar</h1>
  <div class="months" *ngFor="let month of months">
    <div class="month">
      <ul>
        <li>
          {{month.month}}<br>
          <span style="font-size:18px">{{currentYear}}</span>
        </li>
      </ul>
    </div>

    <ul class="weekdays">
      <li>Su</li>
      <li>Mo</li>
      <li>Tu</li>
      <li>We</li>
      <li>Th</li>
      <li>Fr</li>
      <li>Sa</li>
    </ul>

    <ul class="days">
      <li *ngFor="let day of month.days; let i=index">{{i}}</li>
    </ul>
  </div>
</div>

Right now, I just get an error saying that it couldn't find a "differ supporting object '31' of type 'number'." I'm pretty sure this is because I didn't do something right to allow my ngFor to count from 1 to 31 or however many days there are in each month, but I don't know how to go about doing that. Any help is greatly appreciated, thanks!

rcarcia02
  • 927
  • 4
  • 15
  • 46
  • 1
    if you are looking to make a datepicker there is a brilliant tutorial here (can also be used to just view dates) https://medium.com/@chiodigiovanni1/how-to-build-a-datepicker-with-angular-bulma-and-moment-js-part-1-54afcd565c2 – Andrew Allen Jun 12 '19 at 18:24
  • 2
    Note that the number of days in February will be incorrect approximately every 4 years or so... – Heretic Monkey Jun 12 '19 at 18:34
  • @AndrewAllen I'm looking to create the same look as a datepicker, just without the clickable functionality and to view all of the months at once instead of just one so I'll definitely check this out because I'm having trouble thinking about how to figure out which day of the week each day starts on, etc. thanks! – rcarcia02 Jun 12 '19 at 18:46
  • 1
    I think you need to utilise some kind of date library or the Date object. I’m lazy so moment.js is what i’d reach for but there’s no reason you can’t use JavaScript Date with methods like getDay(). https://stackoverflow.com/a/13669839/4711754 and https://stackoverflow.com/a/315767/4711754 – Andrew Allen Jun 12 '19 at 20:07

2 Answers2

1

You need to iterate over an array to make the *ngFor work, this means that you need to make an array from the number of days «as @srjkaa said on his example».

you can do something like {remember to add +1 to the index}:

 <li *ngFor="let day of monthDays(month.days); let j=index">{{j+1}}</li>

And your method would be:

monthDays(number){
  return new Array(number);
}

This will be better that using a for loop, its not optimal, it will increase O(^n). i.e. https://stackblitz.com/edit/angular-wymat2

Pablo Palacios
  • 2,767
  • 20
  • 37
  • ah okay, I knew there was a way to do this without creating a separate array inside my array of objects. thanks! – rcarcia02 Jun 12 '19 at 18:45
0

Your problem is what you are trying to iteratee over "Number". In month object you have:

{ month: "January", days: 31 },

And you are trying to iterate over 31. If you will have an array of days like:

{ month: "January", days: [31, ...] }

It will work.

I didn't do something right to allow my ngFor to count from 1 to 31 or however many days there are in each month, but I don't know how to go about doing that. Any help is greatly appreciated, thanks!

If you want to create an array of numbers from 1 to your day in object you can declare a method in your class which will generate if for you like this:

public getMonthDays(daysCount: number): Array<number> {
  const resultArray = [];
  for (let i = 1; i <= daysCount; ++i) {
    resultArray.push(i);
  }
  return resultArray;
}

And use it in html as following:

<ul class="days">
  <li *ngFor="let day of getMonthDays(month.days)">{{day}}</li>
</ul>
srjkaa
  • 336
  • 1
  • 5