1

I have a requirement where I need to create a multi level grid. Where when user clicks on checkbox a child grid will be opened. Please look at HTML shown below:

<table>
   <thead>
     <tr>
       <th>check</th>
       <th>Result</th>                                            
     </tr>
    </thead>
     <tbody>
         <tr>
           <td><label class="checkbox"><input type="checkbox"><a>test</a></label></td>
           <td> Description</td>
          </tr>
          <tr>
            <td colspan="12">
              <table>
                 <tr>
                    <td><label class="checkbox"><input type="checkbox"><a>testing</a></label></td>
                    <td>description</td>          
                 </tr>
               </table>
            </td>
         </tr>
     </tbody>
  </table>

Something similar as shown here: http://dojo.telerik.com/uQEx. I have written angular code for it. And I have wrapped tr in *ngfor to show high level. Please look at code shown below:

<tr *ngFor = "let data of values">
  <td>
     <label class="checkbox">
        <input type="checkbox">
     </label>
     <a (click) = "getTerms(data.id)">{{data.id}}</a>
  </td>
  <td>{{data.desc}}</td>
</tr>

I need to append another list when I click on a tag that is data.id. I am confused how to append response of sub terms in html. Please let me know if you have any suggestion. Also I don't want to use any plugin for it.

EDIT:

The response I am getting on page load is:

[
 {id:1, desc:'test', level: 0},
 {id:2, desc:'testing',level: 0}
]

And now when I click on id =1 column I am sending service request: /get/Term/1 And I am getting response:

[ {id:5, desc: 'test test', level: 1} ]

In the similar way now if I click on id=5 I will get response as: [ {id:8, desc: 'test test test', level: 2} ]

Hope now its clear.

Tavish Aggarwal
  • 1,020
  • 3
  • 22
  • 51

2 Answers2

3

Tavish the question is: What do you have? What do you want obtain? ... As you are add items to your data, one idea is that At first you have

this.data=[
 {id:1, desc:'test', level: 0},
 {id:2, desc:'testing',level: 0}
]

If click "1" you received

[ {id:5, desc: 'test test', level: 1} ]

It's good that you change your data adding "children". So in getData(data.id,i)

//we pass as argument the index too
getData(id:number,index:number)
{
     this.httpClient.get("url"+id).subscribe(res=>{
           this.data[index].children=res
     }
}

So, your data becomes

this.data=[
 {id:1, desc:'test', level: 0,children:
   [ {id:5, desc: 'test test', level: 1} ]
 },
 {id:2, desc:'testing',level: 0}
]

Now you only need to using two *ngFor

<div *ngFor="let level0 of data;let index=i">
    {{level0.id}}{{level0.desc}}{{level0.level}}
    <button (click)="getData(level0.id,index)">click</button>
    <div *ngFor="let level1 of level0.children">
       {{level1.id}}{{level1.desc}}{{level1.level}}
    </div>
</div>

This idea work if you need fews levels, but if you have more that two or three levels can be a nightmire

With more levels you need, when received the data push in data but add the id_parent

getData(id:number)
{
     this.httpClient.get("url"+id).subscribe(res=>{
           res.forEach(x=>{
             //¡¡IMPORTANT!! not {parent.id,..x}
             this.data.push({...x,parent:id})
           })
     })
}

So, your data becomes

this.data=[
 {id:1, desc:'test', level: 0}
 {id:2, desc:'testing',level: 0}
 {id:5, desc: 'test test', level: 1,parent:1}
]

if you have a function like

listData(parent:number)
{
    return (parent)? this.data.filter(x=>x.parent==parent)
                   : this.data.filer(x=>!x.parent)
}

Your *ngFor can be like

<div *ngFor="let level0 of data;let index=i">
    {{level0.id}}{{level0.desc}}{{level0.level}}
    <button (click)="getData(level0.id)">click</button>
    <div *ngFor="let level1 of listData(level0.id)">
       {{level1.id}}{{level1.desc}}{{level1.level}}
    </div>
</div>
Eliseo
  • 50,109
  • 4
  • 29
  • 67
3

Example to show a "iterate" component

//app.component
@Component({
  selector: 'app-root',
  template:`
  <app-app-children [children]="data"></app-app-children>
  `
})
export class AppComponent {
  title = 'app';
  isdisabled:boolean=false;
  data=[{id:1},
        {id:2,
            children:[{id:4},{id:5},{id:6,
                      children:[{id:9},{id:10}]}]},
        {id:3,
             children:[{id:7},{id:8}]}
        ];

  constructor(){}
}


//app-children
@Component({
  selector: 'app-app-children',
  template:`
  <p>
  app-children works!
</p>
<div *ngFor="let item of children">{{item.id}}
  <div *ngIf="item.children">
      <app-app-children [children]="item.children"></app-app-children>
  </div>
</div>`
})
export class AppChildrenComponent {

  constructor() { }
  @Input() children

}

//If whe can have a table, We can change the template like:
@Component({
    selector: 'app-app-children',
    template: `
    <table>
      <thead>
        <th>#</th>
      </thead>
      <tbody>
      <tr *ngFor="let item of children">
        <td>
           <div>
            {{item.id}}
           </div>
           <div *ngIf="item.children">
            <app-app-children [children]="item.children"></app-app-children>
           </div>
        </td>
    </table>
    `,
    styles:[`
      table, th, td {
         border: 1px solid black;
         margin-left:2rem;
      }
      `
     ]
  })
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Thanks! But I don't have data of children's at page load. I will be getting data for id when I click on it. – Tavish Aggarwal Mar 26 '18 at 06:55
  • @TavishAggarwal, I put as you can implement add "children" to your data when you make "click" :( – Eliseo Mar 26 '18 at 06:57
  • Yes. Sorry. I just saw that and was thinking about which approach should I use. – Tavish Aggarwal Mar 26 '18 at 06:58
  • I have code as ``. ISsue is using this way all columns are coming in 1st th only. Any solution?
    – Tavish Aggarwal Mar 26 '18 at 08:41
  • Using the code shown above, there will be multiple table headings that can created. Can you please share plunk link if possible? Thanks! – Tavish Aggarwal Mar 26 '18 at 09:41
  • sorry I'am in hurry. by the way, try using css app-children { display: inline-block; }, and use ng-container if you don't want to create extra divs – Eliseo Mar 26 '18 at 11:35
  • I have created recursive component but I have question on appending childrens dynamically: https://stackoverflow.com/questions/49506270/how-to-append-children-to-object-dynamically. Can you please answer it? – Tavish Aggarwal Mar 27 '18 at 11:00