1
votes

In the new Angular Material Tree component, this is a part of the markup used in the examples (Angular Material tree with flat node example):

<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
    <button mat-icon-button matTreeNodeToggle
            [attr.aria-label]="'toggle ' + node.filename">
      <mat-icon class="mat-icon-rtl-mirror">
        {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
      </mat-icon>
    </button>
    {{node.filename}} : {{node.type}}
</mat-tree-node>

Note that there is an interpolation inside the mat-icon tag which determines which icon to show.

I am using font awesome in my project instead of the Material Design icons, so I am trying to find a way to make the tree component work with font awesome icons.

So far I have tried to replace the mat-icon tag with the following:

<i class="{{treeControl.isExpanded(node) ? 'fas fa-chevron-down' : 'fas fa-chevron-right'}}"></i>

I also tried where Font Awesome is registered so that I can use this:

<mat-icon fontIcon="{{treeControl.isExpanded(node) ? 'fa-chevron-down' : 'fa-chevron-right'}}"></mat-icon>

In both cases, the chevron-right icon appears initially, and clicking to expand works, but the icon does not change. However, if I expand several levels, then collapse the top level, then expand the top level again, all the lower levels show the correct icon (chevron-down).

It seems that treeControl.isExpanded(node) is not executing at the expected time (when the icon button is clicked). Are there any solutions for this problem?

Here is a stackblitz which demonstrates the problem: https://stackblitz.com/edit/angular-fx4glo?file=app%2Ftree-flat-overview-example.html

2

2 Answers

4
votes

Angular attributes and interpolations

This is normal. When you put an interpolation in an attribute's value, like e.g.

class="{{ myFunction() }}"

Angular will call myFunction() just once (when the element is created).

What you need here is a property binding (aka one-way databinding), that is, enclosing an attribute in square brackets.

Please note that it won't work out-of-the-box with the class attribute: to bind a value to the class attribute, you can use [ngClass] directive, like this:

<i class="fas" [ngClass]="{'fa-chevron-down':treeControl.isExpaned(node), 'fa-chevron-right':!treeControl.isExpaned(node) }"></i>

Solution: library interference

The problem in this case was, you were using the JS version of FontAwesome - which works fine in most cases, but not when it comes to change the icon class on-the-fly.

This issue is solved by using the classic, css-font flavor of FontAwesome, that is, adding the link you find here instead of the script.

Please have a look at the forked Stackblitz here: https://angular-fx4glo-2mjlrg.stackblitz.io

Reference: Property binding, ngClass directive

0
votes

Solution for Font Awesome 5 (SVG):

.html

<ng-container *ngFor="let socialItem of socialItems">
    <a
      href="{{ socialItem.url }}"
      target="_blank"
      attr.aria-label="{{ socialItem.name }}. Click here to check our {{ socialItem.name }}."
      role="menuitem"
      title="{{ socialItem.name }}"
      ><fa-icon [icon]="socialItem.icon"></fa-icon>
    </a>
</ng-container>

.ts

public socialItems: {
    icon: [string, string];
    name: string;
    url: string;
  }[] = [
    {
      icon: ['fab', 'behance'],
      name: 'Behance',
      url: 'https://behance.net'
    },
    ... // Next elements of socialItems...
}

Assuming that all steps here has been performed in order to import FontAwesome module with its icons it works.