Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create multiple elements in loop Angular2

Edit: About the possible answer: I came across that question/answer too and implemented it that way. However, with the new version of Angular2 the syntax is different. The documentation about ngFor wasn't updated (this is where I looked). So I wrote the wrong code. The documentation about ngFor is updated in the Template Syntax - ngFor. Günter wrote a correct example on how to use it in the newer versions of Angular2 (beta17 or higher).

I'd like to create multiple elements in a loop. This is what I have now:

<table>
    <thead>
        <th>ID</th>
        <th>Name</th>
    </thead>
    <tbody>
        <tr *ngFor="let item of items" class="info">
            <td>{{ item['id'] }}</td>
            <td>{{ item['name'] }}<td>
        </tr>
    </tbody>
</table>

What I'd like is under ever tr another tr with details. The desired output should look like this in the browser:

<table>
    <thead>
        <th>ID</th>
        <th>Name</th>
    </thead>
    <tbody>
        <tr class="info">
            <td>1</td>
            <td>Item 1<td>
        </tr>
        <tr class="details">
            <!-- More detailed info about item 1 -->
        </tr>
        <tr class="info">
            <td>2</td>
            <td>Item 2<td>
        </tr>
        <tr class="details">
            <!-- More detailed info about item 2 -->
        </tr>
    </tbody>
</table>

How can I achieve the desired result?

like image 480
Starfish Avatar asked May 12 '16 08:05

Starfish


4 Answers

<template ngFor [ngForOf]="items" let-item> is the canonical for of *ngFor and allows to repeat more than one element.

import {Component} from '@angular/core'

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>Hello {{name}}</h2>
<table>
    <thead>
        <th>ID</th>
        <th>Name</th>
    </thead>
    <tbody>
      <template ngFor [ngForOf]="items" let-item>
        <tr class="info">
          <td>{{ item['id'] }}</td>
          <td>{{ item['name'] }}<td>
        </tr>
        <tr class="details">
          <td>{{ item['description'] }}<td>
        </tr>
      </template>    
    </tbody>
</table>

    </div>
  `,
  directives: []
})
export class App {
  items = [
    {name: 'name1', id: 1, description: 'description1'}
    {name: 'name2', id: 2, description: 'description2'}
    {name: 'name3', id: 3, description: 'description3'}
  ];
  constructor() {
    this.name = 'Angular2 (Release Candidate!)'
  }
}

Plunker example

In contrary to Polymer (for example), using <template> within <tbody> (or other table elements <tr>, ...) also works fine in IE with Angular2, because Angular2 processes the template internally and never adds it to the DOM. In Polymer this would not work because IE removes "unexpected" tags from table elements (which breaks Poymers <template is="dom-repeat">) See also http://caniuse.com/#search=template

like image 197
Günter Zöchbauer Avatar answered Oct 17 '22 01:10

Günter Zöchbauer


Use following component code:

import { Component } from '@angular/core';

@Component({
  selector: 'demo-app',
  templateUrl: 'app/app.component.html',
  pipes: []
})
export class AppComponent {
  constructor() { 
    this.items = [
        {id: 1, name: 'Bob', details: 'Bob details'},
        {id: 2, name: 'Sarah', details: 'Sarah details'},
        {id: 3, name: 'Sam', details: 'Sam details'},
        {id: 4, name: 'Susan', details: 'Susan details'}
    ];
  }
}

With following app.component.html file:

<table>
    <thead>
        <th>ID</th>
        <th>Name</th>
    </thead>
    <tbody>
      <template ngFor [ngForOf]="items" let-item>
        <tr class="info">
            <td>{{ item['id'] }}</td>
            <td>{{ item['name'] }}<td>
        </tr>
        <tr class="details">
            <td colspan=2>{{ item['details'] }}</td>
            <!-- More detailed info about item -->
        </tr>
      </template>
    </tbody>
</table>

Result is something like this:

<table>
    <thead>
        <th>ID</th>
        <th>Name</th>
    </thead>
    <tbody>
        <tr class="info">
            <td>1</td>
            <td>Bob</td><td>
        </td></tr>
        <tr class="details">
            <td colspan="2">Bob details</td>                
        </tr>          
        <tr class="info">
            <td>2</td>
            <td>Sarah</td><td>
        </td></tr>
        <tr class="details">
            <td colspan="2">Sarah details</td>                
        </tr>          
        <tr class="info">
            <td>3</td>
            <td>Sam</td><td>
        </td></tr>
        <tr class="details">
            <td colspan="2">Sam details</td>                
        </tr>          
        <tr class="info">
            <td>4</td>
            <td>Susan</td><td>
        </td></tr>
        <tr class="details">
            <td colspan="2">Susan details</td>                
        </tr>          
    </tbody>
</table>

For more information read https://coryrylan.com/blog/angular-2-ng-for-syntax

like image 34
gevorg Avatar answered Oct 17 '22 03:10

gevorg


You can achieve this by looping on <tbody> instead of <tr>, as tables with mutiple tbody is valid in html refer to.

So your code will be like

<table>
        <thead>
            <th>ID</th>
            <th>Name</th>
        </thead>
        <tbody *ngFor="let item of items; #idx = index">
            <tr class="info">
                <td>{{idx}}</td>
                <td>Item {{idx}}<td>
            </tr>
            <tr class="details">
                <td>{{ item['id'] }}</td>
                <td>{{ item['name'] }}<td>
            </tr>
         </tbody>
    </table>
</table>
like image 1
Praveen Kumar P Avatar answered Oct 17 '22 01:10

Praveen Kumar P


Since Angular v4 <template> tag is deprecated. Use <ng-template> instead, as described in tutorial: ng-template-element

like image 1
Mate Šimović Avatar answered Oct 17 '22 02:10

Mate Šimović