Twitter LogoFacebook Logo
Bottom Sheet
Hello, in this tutorial, I will be talking about the Bottom Sheet component from Angular Material.
By: King

The bottom sheet component is a container that appears at the bottom area of the screen when triggered.

You need 2 things for the component:

1) a trigger to activate the bottom sheet
2) a component for the contents inside the bottom sheet

Image from Codeible.com

Implementation

To begin, add the MatBottomSheetModuel to your project. Go to the app module file, add the import statement, and add it to the app.

App Module File

...
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    ...
    MatBottomSheetModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { 
  constructor(){

  }
}

Using the Bottom Sheet

Go into a HTML page and add a button to trigger the bottom sheet. Attach a click event to it so we can click on the button to activate the bottom sheet.

App Component HTML

<button (click)="onTriggerSheetClick()">Trigger Sheet</button>

Go into the TypeScript file and define the method for the click event.

onTriggerSheetClick(){
    
}

Import MatBottomSheet from Angular Material Bottom Sheet and inject it in the constructor of the class. Then call the open() method inside the click function to active the bottom sheet. 

...
import { MatBottomSheet } from '@angular/material/bottom-sheet';

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

  
  constructor(private matBottomSheet: MatBottomSheet) {

  }

   onTriggerSheetClick(){
       this.matBottomSheet.open();
   }

}

For the argument, we need to pass in the component that will be used for the bottom sheet. Since we do not have a component for the sheet, we cannot pass anything yet. 


Create a new component. Open the terminal in Visual Studio Code and run the ng generate component command.

ng generate component Template

Once the component files are generated, pass in the name of the component in the open method. 

 onTriggerSheetClick(){
     this.matBottomSheet.open(TemplateComponent);
 }

For Angular 8 and below

If you are using Angular 8 and below, make sure to add the component that the bottom sheet is using inside the entryComponents array in the app module file. 

App Module File

import { TemplateComponent } from './template/template.component';
...

@NgModule({
  declarations: [
    AppComponent
  ],
  entryComponents: [
    TemplateComponent
  ],
  imports: [
    BrowserModule,
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { 
  constructor(){

  }
}

You need to do this for Angular versions below 9 because of how the project is compiled. For efficiency, the compiler will only compile the components that are declared in the code. 


For example, to successfully declare that the TemplateComponent, we need to take the value of selector and add it inside of an HTML page.  

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

}

HTML

<app-template></app-template>

Since this was not necessary for the bottom sheet, the component needs to be added to the entryComponents array.

Transferring Data Into the Bottom Sheet

To transfer data into the sheet


1) add a new JSON object argument in the open method
2) add a property call data
3) pass in the data that you want to transfer. 

 onTriggerSheetClick(){
     this.matBottomSheet.open(
         TemplateComponent,
          {
              data: "Template for Bottom Sheet"
          }
     );
 }

Then go into the TypeScript file for the Template Component and import MAT_BOTTOM_SHEET_DATA from Angular Material bottom-sheet. Then inject the data inside the constructor by using the inject() decorator. 

import { MAT_BOTTOM_SHEET_DATA } from '@angular/material/bottom-sheet';

@Component({
  selector: 'app-template',
  templateUrl: './template.component.html',
  styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
     constructor(
       @Inject(MAT_BOTTOM_SHEET_DATA) public data 
     ) { }
}

For the type, use the type of the data that was passed in. If we take a look at our code, we are passing in a string, so the type of our data will be a string.

{
   data: "Template for Bottom Sheet"
}

export class TemplateComponent implements OnInit {
     constructor(
       @Inject(MAT_BOTTOM_SHEET_DATA) public data: string
     ) { }
}

Now our data is successfully transferred and it can be used within the sheet.

Template Component HTML

<p>{{data}}</p>

For more complex data, we can pass in an JSON object instead. 

{
   data: {
       title: "Bottom Sheet Example",
       message: "Template for Bottom Sheet"
   }
}

export class TemplateComponent implements OnInit {
     constructor(
       @Inject(MAT_BOTTOM_SHEET_DATA) public data: title: string, message: string}
     ) { }
}

<p>{{data.message}}</p>

Transferring Data Out

To transfer data out from the bottom sheet. Go to the Bottom Sheet component TypeScript file and add MatBottomSheetRef to the imports. Then inject it inside the constructor.

import 
   MAT_BOTTOM_SHEET_DATA,
   MatBottomSheetRef
 from '@angular/material/bottom-sheet';

@Component({
  selector: 'app-template',
  templateUrl: './template.component.html',
  styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
     constructor(
       @Inject(MAT_BOTTOM_SHEET_DATApublic data title: string, message: string},
       private bottomSheetRef: MatBottomSheetRef
     ) { }
}

Override the ngOnDestroy() method, call the dismiss method from the BottomSheetRef object, and then pass in the data that you want to transfer.

@Component({
  selector: 'app-template',
  templateUrl: './template.component.html',
  styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
     constructor(
       @Inject(MAT_BOTTOM_SHEET_DATA) public data { title: string, message: string},
       private bottomSheetRef: MatBottomSheetRef
     ) { }

    ngOnDestroy(){
        this.matBottomSheetRef.dismiss(this.data);
    }
}

Lastly, go back to the function that triggers the sheet.
Declare a reference to the trigger, then call the afterDismissed() method, and subscribe to it. 

 onTriggerSheetClick(){

     let bottomSheet = 
        this.matBottomSheet.open(
         TemplateComponent,
             {
                 data: {
                     title: "Bottom Sheet Example",
                     message: "Template for Bottom Sheet"
                 }
             }
        );

     bottomSheet.afterDismissed().subscribe(
        (result) => {

        }
     );
     
 }

The results argument represents the data that we passed in the dismiss method. 

bottomSheet.afterDismissed().subscribe(
    (result) => {
         alert(result.message);
     }
);

Whenever the dialog close, we can get the data.

Image from Codeible.com

Modifying Default Behaviors

We can also override the default settings for the sheet. 


For example, we can prevent the sheet from closing when we click on the dark area. 

1) Locate the code where you called the open method
2) Inside the JSON object where you passed in the data add the disableClose property and set it to true

let bottomSheet = 
   this.matBottomSheet.open(
     TemplateComponent,
     {
         data: {
               title: "Bottom Sheet Example",
               message: "Template for Bottom Sheet"
         },
         disableClose: true
     });

This will prevent the sheet from being closed when the user clicks outside of the sheet. 

We can also remove the dark area. Add the hasBackdrop property and set it to false. 

let bottomSheet = 
   this.matBottomSheet.open(
     TemplateComponent,
     {
         data: {
               title: "Bottom Sheet Example",
               message: "Template for Bottom Sheet"
         },
         disableClose: true,
         hasBackdrop: false
     });

For the full list and details, visit the Angular Material website.


Sign In