Eladerezador
Eladerezador

Reputation: 1311

Angular - Create component tree menu

I am creating a tree menu, visually it looks like this:

enter image description here

The tree has been created based on an array of objects obtained from a service, extracted from a date property.

Now, I have to get the tree menu to allow displaying and collapsing the: years, months and complete dates, in the style of this component: https://angular2-tree.readme.io/

Ideally, I'd do this with typescript, but if it's hard for me, I'd try using an external component.

This is the html code:

<ul>
        <li *ngFor="let y of tree | keyvalue">{{y.key}}
            <ul>
                <li *ngFor="let m of tree[y.key] | keyvalue">{{m.key}}
                    <ul>
                        <li *ngFor="let d of tree[y.key][m.key] | keyvalue">{{d.key}}
                            <ul>
                                <li *ngFor="let h of tree[y.key][m.key][d.key]"><a [ngClass]="{'hourSelected': (idSchedule === h.id || lastId === h.id),'hourUnSelected': idSchedule !== h.id}" (click)="loadMacroProcesses(h.id)">{{h.hour}}</a></li>
                            </ul>    
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>

This would be the solution, now I will refine it:

    <ul>
        <li id="year" *ngFor="let y of tree | keyvalue; let i=index" (click)="listClick($event, i)">{{y.key}}
            <ul [hidden]="indexExpandedYear!=i?true:null">
                <li id="month" *ngFor="let m of tree[y.key] | keyvalue; let j=index" (click)="listClick($event, j)">{{m.key}}
                    <ul [hidden]="indexExpandedMonth!=j?true:null">
                        <li id="day" *ngFor="let d of tree[y.key][m.key] | keyvalue; let k=index" (click)="listClick($event, k)">{{d.key}}
                            <ul [hidden]="indexExpandedDay!=k?true:null">
                                <li *ngFor="let h of tree[y.key][m.key][d.key]"><a [ngClass]="{'hourSelected': (idSchedule === h.id || lastId === h.id),'hourUnSelected': idSchedule !== h.id && lastId !== h.id}" (click)="loadMacroProcesses(h.id)">{{h.hour}}</a></li>
                            </ul>    
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>

This is the typescript method:

 listClick(event, i) {
        switch (event.srcElement.id) {
                case "year":
                    this.indexExpandedYear = this.indexExpandedYear==i?-1:i;
                    event.stopPropagation();
                break;
                case "month":
                    this.indexExpandedMonth = this.indexExpandedMonth==i?-1:i;
                    event.stopPropagation();
                break;  
                case "day":
                    this.indexExpandedDay = this.indexExpandedDay==i?-1:i;
                    event.stopPropagation();
                break;       
            default:
                break;
        }
    }

Can you recommend me a good one external component? Thanks.

NOTE: I am working with version 11 of Angular

NOTE: If you deploy one year, the rest of the years should be collpased back.

NOTE: Angular material is not valid for me

Upvotes: 0

Views: 357

Answers (2)

Jibin Philipose
Jibin Philipose

Reputation: 74

You should checkout the tree component provided by primeng. It has its own data format and can do your own customisation on top it.

Upvotes: 0

LaughByte
LaughByte

Reputation: 164

You could add a parameter for visibility and click event to the parent ul. How it would work is that they would have a boolean value on them for visibility that would change when you click the top ul element. You would have a method that would just switch between true/false and display if true hidden if false. Click event should be on the top li element and visibility on its child.

Upvotes: 1

Related Questions