Is there a way to showcase just the month in one spot when presenting data using Angular 13?

Just starting out with Angular and facing a challenge in the Milestone section. There is a loop for displaying years and months, but I need to ensure that the month name is displayed only once for each specific year. Can someone provide me with a possible solution? Below are my HTML and TypeScript codes:

HTML Code

<section class="milestone-wrapper">
    <section class="milestone-wrap-info">
        <ul class="timeline">
            <li *ngFor="let milestone of formattedMileStoneData">
                <div class="direction-r">
                    <div class="flag-wrapper">
                        <span class="flag">{{milestone.Year}}</span>
                    </div>
                    <div class="desc" *ngFor="let month of milestone.Month">
                        <label>{{month.MonthName}}</label>
                        <p>{{month.Details}}</p>
                    </div>
                </div>
            </li>
        </ul>
    </section>
</section>

Provided Data:

"data": [
            {
                "Id": "42",
                "Year": "2021",
                "MonthName": "December",
                "Details": "Introduce Minimum Wage Allowance for government staff",
                "DisplayOrder": "3",
                "LanguageID": "1",
                "Hide": "0"
            },
            {
                "Id": "41",
                "Year": "2021",
                "MonthName": "December",
                "Details": "Complete the pay structure model used in the Pay Framework",
                "DisplayOrder": "2",
                "LanguageID": "1",
                "Hide": "0"
            },
            {
                "Id": "18",
                "Year": "2021",
                "MonthName": "October",
                "Details": "Formulate the Job Evaluation Guidelines",
                "DisplayOrder": "1",
                "LanguageID": "1",
                "Hide": "0"
            }];

My TypeScript Code:

this.formattedMileStoneData = this.allMileStones.reduce((a: any, b: any) => {
            const element = a.find((x: any) => x.Year == b.Year);
            if (element) element.Month.push(b);
            else a.push({ Year: b.Year, Month: [b] });
            return a;
          }, []);

The current result can be seen here.

The desired result should look like this.

If you have any suggestions on how to achieve the desired outcome, please help me out. Thank you!

Answer №1

Hey there! I've put together a codesandbox link for you that should meet your requirements. Check it out here!

In my TypeScript code, I defined two member variables named currentYear and currentMonth which are initially set to empty strings.

The logic checks the current year against the year of each iteration in the loop. If they match, the year is not displayed. If not, the current year is updated and displayed.

  displayYear(year: string): boolean {
    if (year === this.currentYear) {
      return false;
    } else {
      this.currentYear = year;
      return true;
    }
  }

A similar approach is taken with checking the month.

  displayMonthName(year: string, month: string): boolean {
    if (year === this.currentYear && month === this.currentMonth) {
      return false;
    } else {
      this.currentYear = year;
      this.currentMonth = month;
      return true;
    }
  }

This is a simplified version of your code snippet.

<section class="milestone-wrapper">
  <section class="milestone-wrap-info">
    <ul class="timeline">
      <li *ngFor="let milestone of data">
        <div class="direction-r">
          <div class="flag-wrapper">
            <span class="flag" *ngIf="displayYear(milestone.Year)"
              >{{milestone.Year}}</span
            >
          </div>
          <div class="desc">
            <label *ngIf="displayMonthName(milestone.Year, milestone.MonthName)"
              >{{milestone.MonthName}}</label
            >
            <p>{{milestone.Details}}</p>
          </div>
        </div>
      </li>
    </ul>
  </section>
</section>

I recommend avoiding the use of any as it goes against TypeScript's purpose.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Controlling Ionic 3 slides on a separate page

I have a collection of slides on one page, each slide representing a different page. I am looking to create a functionality where clicking a button on one of the pages will advance the slide to the next one: slides-page.ts @ViewChild(Slides) slides: Slid ...

The module "jquery" in jspm, jQuery, TypeScript does not have a default export

Having some trouble setting up a web app with TypeScript and jspm & system.js for module loading. Progress is slow. After installing jspm and adding jQuery: jspm install jquery And the initial setup: <script src="jspm_packages/system.js"></scri ...

Receiving multiple Firebase notifications on the web when the same application is open in multiple tabs

I have implemented firebase push notifications in Angular 7 using @angular/fire. However, I am facing an issue where I receive the same notification multiple times when my application is open in multiple tabs. receiveMessage() { this.angularFireMess ...

Combining multiple Observables and storing them in an array using TypeScript

I am working with two observables in my TypeScript code: The first observable is called ob_oj, and the second one is named ob_oj2. To combine these two observables, I use the following code: Observable.concat(ob_oj, ob_oj2).subscribe(res => { this.de ...

Setting up ng-bootstrap for your project

I'm currently in the process of trying to incorporate the ng-bootstrap package into my application. To ensure I have all the necessary packages, I've executed npm i and updated both the @angular/core and @angular/cli modules to their latest vers ...

Tips for customizing Material UI CSS default properties in React

I'm currently working on a React project and utilizing the 'Table' component from Material UI. The default CSS properties of this table, along with its components like TableHead, TableCell, and TableRow, are proving difficult to override whi ...

The "library" is encountering errors due to missing dependencies, specifically @angular/material/form-field

I've been working with a shared component library project that has been running smoothly for a while now. Recently, I decided to replace some of the custom components with Angular Material components. However, after adding NgMat to the library project ...

Utilizing the default event object in ag-Grid's event methods with JavaScript

I am a newcomer to ag-grid and I need help with calling event.preventDefault() in the "cellEditingStopped" grid event. Unfortunately, I am struggling to pass the default JavaScript event object into it. Is there a way to make this work? Additionally, I al ...

The interfaces being used in the Redux store reducers are not properly implemented

My Redux store has been set up with 2 distinct "Slice" components. The first one is the appSlice: appSlice.ts import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import type { RootState } from "./store"; export interface CounterState { value ...

The Angular 18 component was brought in as a dependency and integrated into the project, but unfortunately, it

How do I properly integrate the NavbarComponent into the template of the app component? https://i.sstatic.net/pBKTzUnf.png app.component.html <app-navbar></app-navbar> <router-outlet></router-outlet> main.ts import {CdkTableModul ...

Enhance your webpage design with stylish CSS formatting using Bulma cards

My HTML output is as follows: https://i.stack.imgur.com/aBdEF.jpg It seems that the footer is not matching up with the cards... The CSS component I am using looks like this: .card-equal-height { display: flex; flex-direction: column; height: 100%; ...

Using Typescript to iterate through an array of objects and modifying their keys using the forEach method

I have an object called 'task' in my code: const task = ref<Task>({ name: '', description: '', type: undefined, level: 'tactic', participants: undefined, stages: undefined, }); export interface Tas ...

Building an AngularJS Service with TypeScript that is Non-Singleton: A Step-by-Step Guide

I need help converting an AngularJS Typescript Service into a Non-Singleton. Can anyone provide guidance on how to achieve this? (Note: This is not the same as other questions that focus on achieving this in JS) I have included some simple pseudo code be ...

Issue R10 (Start-up delay) -> Failure of web application to connect to $PORT in the given 60 seconds after being launched (Angular)

I am currently in the process of building an Angular 7 application and attempting to connect it to Heroku (I am fairly new to using Heroku). Upon trying to run the application on Heroku, I encountered the following error: https://i.stack.imgur.com/ySmJw.p ...

Answer found: How to effectively filter data arrays in a React client application

I've been working on mapping the GraphQL data onto a React app and I'm facing an issue with making the filtration dynamic for user input. Currently, I am using .filter() to apply client-side filtration but struggling to figure out how to make it ...

Receiving warnings during npm installation and encountering difficulties with fixing issues using npm audit fix

Currently, I am working on developing an Angular application with a .NET Core Web API integration. Upon cloning the repository, I attempted to execute 'npm install' for the Angular application, but encountered an unexpected error: npm install n ...

Issue with Angular 4: Radio button defaults not being set

After hardcoding the value in component.ts, I am able to see the pre-selected radio button. However, when attempting to retrieve the value from sessionStorage, it does not work as expected. The value is visible in the console though. Could someone please ...

Display Angular elements within dynamically injected HTML

I am facing an issue with my Angular 15 application. I have a component called FatherComponent, which receives HTML content via an API and injects it into its template using innerHTML: <div [innerHTML]="htmlContent"></div> The proble ...

Using Angular-Meteor to make an HTTP request

I'm attempting to utilize the HTTP.call method with angular-meteor. Within my API backend folder, I am trying the following within a method: this.unblock(); try { const result = HTTP.call('GET', 'https://api.foursquare.com/v2/users/ ...

Strange occurrences with HTML image tags

I am facing an issue with my React project where I am using icons inside img tags. The icons appear too big, so I tried adjusting their width, but this is affecting the width of other elements as well. Here are some screenshots to illustrate: The icon wit ...