
Angular Action Sheet
Description
This is a simple action sheet service that can be used to show action sheets in angular using material.
// action-modal.service.ts
import { CommonModule } from '@angular/common';
import { Component, Injectable, OnInit, inject } from '@angular/core';
import {
MAT_BOTTOM_SHEET_DATA,
MatBottomSheet,
MatBottomSheetConfig,
MatBottomSheetModule,
MatBottomSheetRef,
} from '@angular/material/bottom-sheet';
import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list';
import { firstValueFrom } from 'rxjs';
interface ActionI {
name: string;
cssClass?: string;
}
interface ActionDataI {
actions: { [key: string]: string | ActionI };
}
interface FormattedActionI {
name: string;
cssClass?: string;
key: string;
lines?: string[];
}
@Injectable()
export class ActionModalService {
readonly #bottomSheet = inject(MatBottomSheet);
public async open(data: ActionDataI, options: MatBottomSheetConfig<any> = {}) {
const dialogRef = this.#bottomSheet.open(ActionModalComponent, {
...options,
data: { data },
});
return firstValueFrom(dialogRef.afterDismissed());
}
}
@Component({
standalone: true,
imports: [CommonModule, MatButtonModule, MatBottomSheetModule, MatListModule],
template: `<mat-nav-list>
<button mat-list-item *ngFor="let item of actions" (click)="select(item.key)" [class]="item.cssClass || ''">
<span matListItemTitle>{{ item.name }}</span> <span matLine *ngFor="let line of item.lines">{{ line }}</span>
</button>
</mat-nav-list>`,
})
export class ActionModalComponent implements OnInit {
readonly #bottomSheetRef: MatBottomSheetRef<ActionModalComponent> = inject(MatBottomSheetRef);
readonly #data: { data: ActionDataI } = inject(MAT_BOTTOM_SHEET_DATA);
public actions: FormattedActionI[] = [];
ngOnInit(): void {
const actionList: FormattedActionI[] = this.actions;
const actions = this.#data.data.actions;
Object.keys(actions).forEach((key) => {
const action = actions[key];
let act: FormattedActionI;
if (typeof action === 'string') act = { name: action, key };
else act = { ...action, key };
[act.name, ...act.lines] = act.name.split('\n');
actionList.push(act);
});
}
select(key: string) {
this.#bottomSheetRef.dismiss({ action: true, key });
}
}
Styling
For styling the alert modal, you have to override the following css variables. in global styles.scss file.
.mat-mdc-list-base {
--mdc-list-list-item-label-text-color: inherit;
--mdc-list-list-item-hover-label-text-color: inherit;
}
Setup
Import the ActionModalService
and ActionModalComponent
into your app module and add them to the providers and imports array respectively.
Usage
import { Component } from '@angular/core';
import { ActionModalService } from './action-modal.service';
@Component({
selector: 'test-page',
standalone: true,
imports: [CommonModule],
template: `<button (click)="remove(id)">Delete</button> `,
})
export class TestComponent implements OnInit {
#actionModalService = inject(ActionModalService);
async remove(id: number) {
const result = await this.#actionModalService.open({
actions: {
test: 'Test\nThis is just a test',
test2: 'Test2',
test3: 'Test3',
test4: {
name: 'Test4',
cssClass: 'red-500',
},
},
});
console.log(result);
}
}