skip to Main Content

I have been working an app with Angular 8.

The employee-list component displays data in a table.

In employee-list.component.ts I have:

import { Component } from '@angular/core';
import { Employee } from '../../models/empModel';
import * as data from '../../data/employees';

@Component({
  selector: 'app-employee-list',
  templateUrl: './employee-list.component.html',
  styleUrls: ['./employee-list.component.css'],
})
export class EmployeeListComponent {
  public displayMode: String = 'grid';
  public deptno: number = -1;
  public empsArray: Employee[] = data.employees;

  public removeEmployee(empno: number) {
    this.empsArray = this.empsArray.filter((item) => item.empno != empno);
  }

  public filterByDepartment(num: number) {
    this.deptno = num;
  }

  public setDisplayMode(mode: String) {
    this.displayMode = mode;
  }
}

In the view:

<div class="table-responsive">
    <table class="table table-striped">
      <thead>
        <tr>
          <th>Full Name</th>
          <th>Job</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let employee of empsArray | filter: deptno">
          <app-employee-table-item
            [employee]="employee"
          ></app-employee-table-item>
        </tr>
      </tbody>
    </table>
  </div>
  

As can be seen above, the contents of each table row is handled by a (child)component, called employee-table-item:

import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Employee } from '../../models/empModel';

@Component({
  selector: 'app-employee-table-item',
  templateUrl: './employee-table-item.component.html',
  styleUrls: ['./employee-table-item.component.css'],
})
export class EmployeeTableItemComponent {
  @Input() employee: Employee;
}

The problem

The table is diplsyed wrongly, due to the fact that the contents of every table row is wrapped in a <app-employee-table-item></app-employee-table-item> element.

I want display the contents of every table row directly in the tag, while keeping the template in a distinct HTML file.

Question

What is the most reliable way to display the contents of every table row directly in the <tr> tag?

2

Answers


  1. A solution would be to use your component as a directive. It is pretty common to do that exactly in your case.

    app-employee-table-item:

    @Component({
      selector: '[appEmployeeTableItem],app-employee-table-item',
      templateUrl: './employee-table-item.component.html',
      styleUrls: ['./employee-table-item.component.css'],
    })
    export class EmployeeTableItemComponent {
      @Input('appEmployeeTableItem') employee: Employee;
    }
    

    EmployeeList.html :

      <tbody>
        <tr
          *ngFor="let employee of empsArray | filter: deptno"
          [appEmployeeTableItem]="employee"
        ></tr>
      </tbody>
    
    Login or Signup to reply.
  2. An approach you can use is to fix this is to change from using a tag selector to using an attribute value selector.

    In employee-list.component.html, replace

    <tr *ngFor="let employee of empsArray | filter: deptno">
        <app-employee-table-item
            [employee]="employee"
        ></app-employee-table-item>
    </tr>
    

    with this:

    <tr
        data-selector="app-employee-table-item"
        *ngFor="let employee of empsArray | filter: deptno"
        [employee]="employee"
    ></tr>
    

    In employee-table-item.component.ts, change the selector to

    selector: '[data-selector=app-employee-table-item]',
    

    Now, instead of looking for <app-employee-table-item> HTML elements, Angular will look for any HTML elements with an attribute called data-selector with value of app-employee-table-item and replace that element with your template.

    Your Stackblitz, forked, with this change: https://stackblitz.com/edit/angular-modal-bootstrap-ke3bbc?file=src%2Fapp%2Fcomponents%2Femployee-list%2Femployee-list.component.html

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search