0

I am trying to implement Hierarchical Grid in my Angular 2 application similar to this one http://demos.telerik.com/kendo-ui/grid/hierarchy

So I started out by creating two components. The Parent Component is for parent table and Child Component is for child table. So when click on row from parent table, the child table will load right below it (like above example).

This is how my html looks like

<div class="row">
    <div class="col-md-12">
        <h1>{{pageTitle}}</h1>
        <table class="table table-striped">
            <thead>
                <tr>
                    <td></td>
                    <td>User Name</td>
                    <td>Email</td>
                    <td>Billing Method</td>
                </tr>
            </thead>
            <tbody>
                <tr class="master-row" *ngFor="#invoice of invoices; #i = index">
                    <td><button (click)="getDetail(invoice)"><i class="glyphicon glyphicon-chevron-right"></i></button></td>
                    <td>{{invoice.username}}</td>
                    <td>{{invoice.email}}</td>
                    <td>{{invoice.billingMethod}}</td>
                </tr>

            </tbody>
        </table>
    </div>
</div>

But I am having two issues:

1) How to load child table on a correct location in DOM? The problem is when my parent table render, all of it's rows gets created using ngFor directive. Now when click on a row, how to load it's child table right below it? How to identify the location?

2) In order to load child table, I was thinking to use DynamicComponentLoader Class, but looks like the communication between Components won't be possible when using DCL.

Please suggest

6
  • You can always nest components. Check this plunker it should guide you Commented Apr 20, 2016 at 11:03
  • @Abdulrahman I want to load nested component when row click on parent table. And want to inject the nested component right below the clicked row. How would I identify the correct location where to put the nested component since DCL require the location in DOM where to load the component? Commented Apr 20, 2016 at 11:08
  • I don't see any good reason for using DynamicComponentLoader in your situation. But here is a simple plunker to show you how to reference the target element. " check the console after clicking on a row" Commented Apr 20, 2016 at 11:14
  • @Abdulrahman Thanks. I see you are using Div based structure, however I am using table based structure. I updated my question, can you please check. I want to put child table right after the clicked row in a separate row. Can you please let me know how that could be possible Commented Apr 20, 2016 at 11:21
  • I am not sure this is possible "cleanly", because tr has to be directly below tbody or table. But, if you want to use DCL, then you need an anchor element that will be between the tr and tbody which will mess up the table. If you want to use *ngIf to show the tr then, tr has to be either inside the parent tr or at the bottom of the table. These kind of table restrictions are the reason I prefer divs Commented Apr 20, 2016 at 11:41

1 Answer 1

1

I was able to fulfill your requirements using the template syntax of ngFor

pre 2.0.0-beta.17 syntax:

<template ngFor #item [ngForOf]="items" #i="index">
    <tr>...</tr>
</template>

2.0.0-beta.17 syntax:

<template ngFor let-invoice [ngForOf]="invoices" let-i="index">
    <tr>...</tr>
</template>

Check out this plunker

In your situation it will be:

<template ngFor let-invoice [ngForOf]="invoices" let-i="index">
    <tr class="master-row" *ngFor="#invoice of invoices; #i = index">
        <td><button (click)="getDetail(invoice)"><i class="glyphicon glyphicon-chevron-right"></i></button></td>
        <td>{{invoice.username}}</td>
        <td>{{invoice.email}}</td>
        <td>{{invoice.billingMethod}}</td>
    </tr>
    <tr *ngIf="isInvoiceOpened(i)">
        <td colspan="100">
            <child-table [details]="details"></child-table>
        </td>
    </tr>
</template>

The isInvoiceOpened() function will return true if that particular row is opened. Which means you should have an array to hold opened rows indexes, i.e.

_openedDetails = [];

isInvoiceOpened(i){
  return this._openedDetails.indexOf(i)>-1;
}

getDetail(i){
  let index = this._openedDetails.indexOf(i);
  if(index > -1)
    this._openedDetails.splice(index,1);
  else
    this._openedDetails.push(i);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.