Use FontAwesome icons in table header in Angular

975 Views Asked by At

I'm trying to set the sort, sortUp, and sortDown icons to my table headers, following the table tutorial from ng-bootstrap.

There's a NgbdSortableHeader directive that changes the sorting of the column:

@Directive({
  selector: 'th[sortable]',
  host: {
    '[class.asc]': 'direction === "asc"',
    '[class.desc]': 'direction === "desc"',
    '(click)': 'rotate()'
  }
})
export class NgbdSortableHeader {
  @Input() sortable: string = '';
  @Input() direction: SortDirection = '';
  @Output() sort = new EventEmitter<SortEvent>();

  rotate() {
    this.direction = rotate[this.direction];
    this.sort.emit({column: this.sortable, direction: this.direction});
  }
}

And the component that has the table:

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.scss'],
  providers: [UserService]
})
export class UsersComponent implements OnInit {
  faSort = faSort;
  faSortUp = faSortUp;
  faSortDown = faSortDown;

  users$: Observable<User[]>;
  total$: Observable<number>;

  @ViewChildren(NgbdSortableHeader) headers!: QueryList<NgbdSortableHeader>;

  constructor() {
  }

  ngOnInit(): void {
  }

  onSort({column, direction}: SortEvent) {
    // resetting other headers
    this.headers.forEach(header => {
      if (header.sortable !== column) {
        header.direction = '';
      }
    });


    this.service.sortColumn = column;
    this.service.sortDirection = direction;
  }
}

I wonder if there's a way to access the current column sorting order and replace the icon from the item or hide them.

<th scope="col" sortable="firstName" (sort)="onSort($event)">
  Name
  <fa-icon [icon]="faSort"></fa-icon>
  <fa-icon [icon]="faSortUp"></fa-icon>
  <fa-icon [icon]="faSortDown"></fa-icon>
</th>
1

There are 1 best solutions below

4
Nicke Manarin On

I was able to solve my issue by using @ChildComponent in the sort directive:

<th scope="col" sortable="firstName" (sort)="onSort($event)">
  Name
  <fa-icon [icon]="faSort" size="lg"></fa-icon>
</th>
import { Directive, EventEmitter, Input, Output, ViewChild, ContentChild, ElementRef } from "@angular/core";
import { FaIconComponent } from "@fortawesome/angular-fontawesome";
import { faSort, faSortUp, faSortDown } from "@fortawesome/pro-regular-svg-icons";

export type SortDirection = 'asc' | 'desc' | '';
const rotate: {[key: string]: SortDirection} = { 'asc': 'desc', 'desc': '', '': 'asc' };

export interface SortEvent {
  column: string;
  direction: SortDirection;
}

@Directive({
  selector: 'th[sortable]',
  host: {
    '[class.asc]': 'direction === "asc"',
    '[class.desc]': 'direction === "desc"',
    '(click)': 'rotate()'
  }
})
export class NgbdSortableHeader {
  @Input() sortable: string = '';
  @Input() direction: SortDirection = '';
  @Output() sort = new EventEmitter<SortEvent>();

  @ContentChild(FaIconComponent) sortIcon?: FaIconComponent;

  rotate() {
    this.direction = rotate[this.direction];
    this.sort.emit({column: this.sortable, direction: this.direction});

    if (this.sortIcon !== undefined)
    {
        this.sortIcon.icon = this.direction === 'asc' ? faSortDown : this.direction === 'desc' ? faSortUp : faSort;
        this.sortIcon.render();
    }
  }
}