Creating organized lists in Angular 4 using list separators

I'm struggling to organize a list with dividers between categories to group items accordingly. Each divider should be labeled with the month name, and the items under it should correspond to that specific month.

My Goal:

- August
  - item 1
  - item 2
- September
  - item 3
  - item 4
  - item 5

Each list item includes a date timestamp from which I extract the month information.

My Attempts:

export class PostItemService {
  groupedItems = [];

  // second item is the date timestamp
  items: item[] = [
    new item('cool title', 1503469292, 'some cool text'),
    new item('second title', 1503469292, 'some cool text'),
    new item('third title', 1503469292, 'some cool text'),
  ];

  splitOnMonth() {

    const items = this.items;
    const groupedItem = [];

    // extract the month number
    function convertTimeStamp(timestamp) {
        const date = new Date(timestamp * 1000);
        const monthNumber = date.getMonth() + 1;

        return monthNumber;
    }

   items.forEach((value, index) => {

      const myMonth = convertTimeStamp(value.date);

      // Stuck at this point, unsure how to proceed

   });

  } // splitOnMonth()

}

I've experimented with various approaches, but I haven't found a solution yet. My main roadblock is determining the next steps from here.

If anyone has faced and resolved a similar challenge or can offer guidance on this issue, I would greatly appreciate it.

Thank you in advance.

Answer №1

To organize your items by month, you can create a map of month objects where each object contains the month's name and an array of items belonging to that month. Iterate through your items, identify their respective months, and push them into the corresponding month's array (creating the object if needed). In your template, iterate through the month array and display items only if they have subitems.

For more details and code examples, please check out this Plunkr link - here


export class PostItemService {

   monthMap: { [index: number]: { monthName: string, items: item[] }};
   monthArray: any[] = [];

   items: item[] = [
      new item('cool title', 1503469292, 'some cool text'),
      new item('second title', 1503469292, 'some cool text'),
      new item('third title', 1503469292, 'some cool text'),
   ];

   constructor() {
       this.monthMap = {  
           1: { monthName: 'January', items: [] },
           2: { monthName: 'February', items: [] },
           3: { monthName: 'March', items: [] },
           // ...rest of the months
       };

       this.splitOnMonth();
   }

   splitOnMonth() {

     var convertTimeStamp = (timestamp) => {
         const date = new Date(timestamp * 1000);
         const monthNumber = date.getMonth() + 1;
         return monthNumber;
     }

     items.forEach((value, index) => {

          const myMonth = convertTimeStamp(value.date);

          this.monthMap[myMonth].items.push(value);
     });

     for (let prop in monthMap) {
        if (this.monthMap[prop].items.length > 0) {
            this.monthArray.push(this.monthMap[prop]);
        }
     }
  }  

}

In a component's template...

<ul class="month-groups">
   <li *ngFor="let month of this.monthArray">
       {{ month.monthName }} 
        <ul class="month-items">
            <li *ngFor="let item of month.items">
                 {{ item.value }}
             </li>
        </ul>
   </li>
</ul>

Remember to style your lists appropriately and consider adding extra margin for nested ones.

Note that there was a missing fat arrow in the forEach function. Additionally, it's advisable to minimize logic in constructors for Angular components. Testing methods like splitMonth() is fine in services but not in components with associated views.

Answer №2

If you're looking to enhance the functionality of your application, consider implementing a Pipe for this purpose.

Take a look at this example:

    @Pipe({
      name: 'ItemsFilterPipe',
      pure: false
    })
    export class ItemsFilterPipe implements PipeTransform {
      transform(items: Item[]): FilteredItem[] {
        // Customize your data processing here, such as creating a new object with timestamp as key and item as value
      }
    }

Then, you can utilize it like this:

*ngFor="let item of items | ItemsFilterPipe"

When used in ngFor, the item will contain {"timestamp": Item[]} pairs.

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

Troubleshooting issue with React and Material UI Table pagination display

Issue with Material UI Table Display When Changing Pages When receiving an array of Artist Objects through props to create a checklist table, I encounter some display issues. The table works fine initially, but when changing pages or sorting, more rows th ...

Guide to positioning an icon at the center of a material card

I am new to CSS and Angular Material, and I need help centering the icon on the card following the design from Figma. I tried copying the CSS from Figma, but it didn't center the icon as expected. Can someone please share techniques to achieve this? S ...

What is the best way to transform Vue JS templates into clean HTML code?

Hello, I've received a request to convert a full VueJS template into pure HTML for use in Angular. While I have access to all of Vue's files and codebase, I'm wondering if there's a fast method to convert these templates into standard ...

Struggling with Angular CLI installation on Mac?

I've been trying to install Angular on my Mac's global directory, but I haven't been successful after multiple attempts. I've tested the following commands: npm install -g @angular/cli npm install -g @angular/cli@latest How to upgrad ...

Include a new course based on a specific situation

Is it possible to conditionally add a specific class using vue js? In my DataStore, I have two values defined in TypeScript: value1: 0 as number, value2: 0 as number Based on the values of value1 and value2, I want to apply the following classes in my te ...

Incorporating a JavaScript file into Angular

I'm looking to incorporate a new feature from this library on GitHub into my Angular project, which will enhance my ChartJS graph. @ViewChild('myChart') myChart: ElementRef; myChartBis: Chart; .... .... const ctx = this.myChart.nativeEleme ...

Navigating the missing "length" property when dealing with partial functions generated using lodash's partialRight

I've been utilizing MomentTimezone for time manipulation within the browser. My development stack includes TypeScript and Lodash. In my application, there is an accountTimezone variable set on the window object which stores the user's preferred ...

What is the best way to update the color of a label in a Mantine component?

When using the Mantine library, defining a checkbox is done like this: <Checkbox value="react" label="React"/> While it's possible to change the color of the checkbox itself, figuring out how to change the color of the label ...

Having an issue with my code in angular 12 where I am unable to successfully call an API to retrieve a token, and then pass that token to another API for further processing

Here is the code snippet containing two methods: getToken and validateuser. I am fetching the token from getToken and passing it as a parameter to validateuser. However, before retrieving the token, my second API call is being executed. ...

Employ the VSTS node API to retrieve all commits within a specified branch

I have been utilizing the vsts-node-api with reasonable success. However, my goal is to retrieve all commits in a specific branch, as detailed in the REST API documentation located here. Unfortunately, the node api only allows for commit queries in a rep ...

What could be causing the undefined properties of my input variables in Angular?

Currently, I am fetching data from a service within the app component and passing it down to a child component using @Input. Oddly enough, when I log the data in ngOnInit, it appears correctly in the child component. However, when I try to assign it to a v ...

ReactNative: When attempting to navigate, a TypeError occurred - this.props.navigation.navigate is not a function

It's confusing to see how this issue is occurring, even though all props have been properly typed. The goal is to pass the navigator to the bottom bar component in order to navigate onPress. Initially, I define the props interface: export interface B ...

Bars of varying heights (Google Chart)

I have incorporated a Google chart within a mat-grid-tile. In this setup, one column displays a value of 50, while the other showcases a value of 30. These particular values are sourced from myService and are accurate. Although when I hover over the bars i ...

Body element in Angular component seems to be mysteriously added at the bottom

<pI'm experiencing something unusual. Every time I render my custom element, the content of the body (innerHTML) of the element is getting appended at the end.</p> <pHere's an example on my homepage - notice how 'childbody' ...

"Embracing Angular2 RC6 with angular-cli: A guide to smoothly upgrading your projects' Angular2 version

After installing angular-cli on a fresh machine, I ran ng --version and received the following: angular-cli: 1.0.0-beta.10 node: 6.5.0 os: win32 x64 It appears to be the latest version according to https://www.npmjs.com/package/angular-cli. When creati ...

Passing a boolean value from the parent Stepper component to a child step in Angular

I am facing an issue with passing the boolean value isNewProposal from a parent Angular Material stepper component to its children steps. Despite using @Input(), the boolean remains undefined in the child component, even after being assigned a value (true ...

Progressive series of observable conditions

The issue at hand: I am faced with the task of checking multiple conditions, some of which lead to the same outcome. Here is the current flow: First, I check if a form is saved locally If it is saved locally, I display text 1 to the user If not saved l ...

Utilizing the MapToIterable Angular Pipe with TypeScript

Exploring the implementation of a pipe in Angular. Discovered that ngFor doesn't work with maps, prompting further research to find a solution. It seems that future features may address this issue, but for now, utilizing a mapToIterable pipe is the re ...

Troubleshooting issue in Angular with loading data before rendering the view

Have you ever come across an issue where you navigate to a component and the table appears empty with no data? I noticed that the component/table is displayed, and the data seems to be in the state (session storage) and loaded. I can only see them if I re ...

Is it possible to integrate the Firestore npm library into my Express application?

Recently, I created my own library to act as a nosql database on my node.js web server in place of mongodb. I came across this interesting quote: Applications that use Google's Server SDKs should not be used in end-user environments, such as on pho ...