The aesthetic of the material tree design is not being reflected as expected

I am attempting to recreate the material tree example showcased here.

This is the desired outcome:

https://i.sstatic.net/dnkm2.png

However, my result appears like this:

https://i.sstatic.net/JXdbo.png

Below is the HTML code I am utilizing:

<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
  <!-- This is the tree node template for leaf nodes -->
  <mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
    <!-- use a disabled button to provide padding for tree leaf -->
    <button mat-icon-button disabled></button>
    {{node.name}}
  </mat-tree-node>
  <!-- This is the tree node template for expandable nodes -->
  <mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
    <button mat-icon-button matTreeNodeToggle
            [attr.aria-label]="'toggle ' + node.name">
      <mat-icon class="mat-icon-rtl-mirror">
        {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
      </mat-icon>
    </button>
    {{node.name}}
  </mat-tree-node>
</mat-tree>

This is my TS (TypeScript) file:

import { Component, HostListener, OnInit, ViewChild, ElementRef } from '@angular/core';
import { ScreenshotService } from './screenshot.service';

import { DomSanitizer, SafeResourceUrl, SafeUrl} from '@angular/platform-browser';

import {FlatTreeControl} from '@angular/cdk/tree';
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';

/**
 * Food data with nested structure.
 * Each node has a name and an optiona list of children.
 */
interface FoodNode {
  name: string;
  children?: FoodNode[];
}

const TREE_DATA: FoodNode[] = [
  {
    name: 'Fruit',
    children: [
      {name: 'Apple'},
      {name: 'Banana'},
      {name: 'Fruit loops'},
    ]
  }, {
    name: 'Vegetables',
    children: [
      {
        name: 'Green',
        children: [
          {name: 'Broccoli'},
          {name: 'Brussel sprouts'},
        ]
      }, {
        name: 'Orange',
        children: [
          {name: 'Pumpkins'},
          {name: 'Carrots'},
        ]
      },
    ]
  },
];

/** Flat node with expandable and level information */
interface ExampleFlatNode {
  expandable: boolean;
  name: string;
  level: number;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {


  private transformer = (node: FoodNode, level: number) => {
    return {
      expandable: !!node.children && node.children.length > 0,
      name: node.name,
      level: level,
    };
  }

  treeControl = new FlatTreeControl<ExampleFlatNode>(
    node => node.level, node => node.expandable);

  treeFlattener = new MatTreeFlattener(
      this.transformer, node => node.level, node => node.expandable, node => node.children);

  dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

  hasChild = (_: number, node: ExampleFlatNode) => node.expandable;

  constructor(private screenshotService: ScreenshotService, private sanitizer: DomSanitizer) {

    this.dataSource.data = TREE_DATA;

  }

}

And here is the app.module.ts file:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { HttpClientModule } from '@angular/common/http';

import {MatTreeModule} from '@angular/material/tree';
import {MatIconModule} from '@angular/material';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatButtonModule} from '@angular/material';
import {FlatTreeControl} from '@angular/cdk/tree';
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';



@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserAnimationsModule,
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    MatTreeModule,
    MatIconModule,
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Answer №1

Dealing with the same issue in Angular 10 led me to discover that along with importing MatTreeModule, I also needed to add MatIconModule and MatButtonModule to the app.module.ts:

import {MatButtonModule} from '@angular/material/button';
import {MatIconModule} from '@angular/material/icon';
import {MatTreeModule} from '@angular/material/tree';
//...
imports: [
  //...
  MatButtonModule,
  MatIconModule,
  MatTreeModule
]

Answer №2

Make sure to include the following URL in your index.html file:

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

Also, ensure that you have imported the MatButtonModule and MatIconModule in your app.module.ts file.

Answer №3

In the event that you have imported everything and it is still not functioning correctly, try debugging the 'level' attribute in the interface or object class.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to make cypress.io swipe an ionic ion-item-sliding component to the left?

I am currently working on a small ionic 4 (vue) app that includes an ion-list with ion-item-sliding. Here is a snippet of the code: HTML <ion-item-sliding v-for="day in month.days" v-bind:key="day.day"> <ion-item :id ...

What is the best way to retrieve environment variables from an NPM package in an Angular 5 application

Is there a method for my node module, created from an Angular 5 application, to access the environment variable from the Angular 5 application (environments/environment.ts)? Perhaps Angular 5 exports its environment variables to JavaScript global variables ...

Custom Validation requires promises to be present

Creating a custom validation method to validate ranges can be done in different ways. Below is an example of how to achieve this: static ratingRange=(min:number,max:number) => { return (control:AbstractControl):Promise<ValidationErrors|null&g ...

Activate Angular Material's autocomplete feature once the user has entered three characters

My goal is to implement an Angular Material Autocomplete feature that only triggers after the user has inputted at least three characters. Currently, I have it set up so that every click in the input field prompts an API call and fetches all the data, whic ...

Investigating the Angular signals that triggered the effect

Is there a way to determine which Angular signal triggered an effect? I have two signals and one effect in a component. One signal is used to start a timer function within a service, while the other signal reacts to changing conditions in the timer functio ...

Utilize ServersideProps to input data into the server-side

Can data be retrieved from the server-side configuration file on the client using getServersideProps() in Next.js? What is the best way to send this data as props or retrieve it in a different manner on the client side? I attempted to use publicRuntimeCo ...

Tooltip implementation in Angular side bar is malfunctioning

I have integrated my angular 7 project side bar with a Tooltip from Angular Material, but I am facing issues with it not working properly. Can anyone guide me on how to correctly add the Tooltip functionality? Thank you. sidebar.component.html <ul cl ...

What are the steps to showcase the content of a Typescript file on an HTML webpage?

We are looking to create a sample gallery with source code examples. Including typescript, html, and HTML files to showcase similar to the Angular.io component samples pages. Is there a way to extract the source code from a typescript file within our pro ...

The Vue property I customized in my component is not being recognized by VSCode(Vetur)

I've successfully implemented a plugin in Vue by declaring it in a main.ts file, defining its type in a plugin.d.ts file, and utilizing it in a component.vue file. Although the compilation is error-free, I am encountering an issue with VSCode intellis ...

The installation of Node on Ubuntu 18.04 encountered an error

Could someone assist me with this problem? I initially had node installed, then uninstalled it using the rm -rf command following online suggestions. Now I am trying to reinstall it using nvm install node However, I'm encountering the following error ...

Making a REST API call with an ID parameter using Angular

I am currently working on an Angular application that interacts with a REST API. The data fetched from the API is determined based on the customer ID, for example: api/incident?customer_id=7. I am unsure of how to incorporate this into the API URL and serv ...

How do I determine if a child component is in a dirty state within CanDeactivateGuard when dealing with multiple form tags?

Currently, I am utilizing a template driven form within my project. The parent component that I am working on is as follows: parent.component.html <tab> <form> <input></input> <button></button> </form ...

The error message "result.subscribe is not a function" indicates that there was a problem

I encountered an issue with the following error message: Uncaught TypeError: result.subscribe is not a function Here's a screenshot of the error for reference: https://i.sstatic.net/yfhy0.png Despite attempting to handle the error, I'm still s ...

Creating adaptable Object Properties using Zod

Just dipping my toes into Typescript, Zod, and Trpc. Let's say I have a schema for animals and plants. I want to keep all their shared properties in the main part of the schema, while putting more specific details into a sub-object named custom. (jus ...

What is the best way to customize the appearance of a mat-checkbox in Angular using Angular Material?

Is there a way to customize the appearance of a mat-checkbox that actually works? I've tried various solutions without success. I attempted to disable view encapsulation and use classes like mdc-checkbox__background, but nothing changed. Even applyin ...

Ways to enable Urql (typescript) to accept Vue reactive variables for queries generated using graphql-codegen

I'm currently developing a Vue project that involves using urql and graphql-codegen. When utilizing useQuery() in urql, it allows for the use of Vue reactive variables to make the query reactive and update accordingly when the variables change. The ...

Guide to iterating through an Observable<Object[]> to generate an array of objects

Google Firestore collection named users is structured as follows : { "contactNumber":"0123456789", "email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="88e2e7e0e6ece7edc8efe5e9e1e4a6ebe ...

The 'getAllByRole' property is not found in the 'Screen' type. TS2339 error

I am currently developing a web application using ReactJs for the front end. While testing the code, I encountered the following error: TypeScript error in My_project/src/unitTestUtils.tsx(79,27): Property 'getAllByRole' does not exist on type & ...

Rearranging data received from an Observable

TL;DR I am working on an Angular app where I need to shuffle an array of names retrieved from a network request and ensure that each group of 6 names selected is unique. However, I noticed duplicates in the selections. Here's a CodePen example using o ...

Tips for assigning a value to a dropdown in Angular

I'm facing an issue with updating the value of a drop-down menu based on certain conditions in my TS file. Here is what my drop-down code looks like: <select [(ngModel)]="selectedEntity" (change)="onChange();"> <option *ngFor="let ite ...