src/app/core/entity-details/entity-bulk-actions/entity-bulk-actions.component.ts
Allow users to select among the registered bulk actions that are available in the current context. Also executes the action.
| selector | app-entity-bulk-actions |
| standalone | true |
| imports |
MatButtonModule
ReactiveFormsModule
BasicAutocompleteComponent
BASIC_AUTOCOMPLETE_COMPONENT_IMPORTS
|
| styleUrls | ./entity-bulk-actions.component.scss |
| templateUrl | ./entity-bulk-actions.component.html |
Properties |
Methods |
|
Inputs |
Outputs |
constructor()
|
| entities | |
Type : Entity[]
|
|
| Required : true | |
|
List of selected entities for bulk actions |
|
| resetBulkActionMode | |
|
Event emitted when the bulk action mode should be exited after an action was executed or the user cancelled the bulk actions. |
|
| cancel |
cancel()
|
|
Returns :
void
|
| Async onActionSelected | ||||||
onActionSelected(action: EntityAction)
|
||||||
|
Parameters :
Returns :
any
|
| actionControl |
Type : unknown
|
Default value : new FormControl()
|
| actionToString |
Type : unknown
|
Default value : () => {...}
|
import {
Component,
inject,
input,
output,
resource,
effect,
} from "@angular/core";
import { FormControl, ReactiveFormsModule } from "@angular/forms";
import { Entity } from "../../entity/model/entity";
import { EntityActionsMenuService } from "../entity-actions-menu/entity-actions-menu.service";
import { EntityAction } from "../entity-actions-menu/entity-action.interface";
import {
BASIC_AUTOCOMPLETE_COMPONENT_IMPORTS,
BasicAutocompleteComponent,
} from "../../common-components/basic-autocomplete/basic-autocomplete.component";
import { MatButtonModule } from "@angular/material/button";
/**
* Allow users to select among the registered bulk actions
* that are available in the current context.
* Also executes the action.
*/
@Component({
selector: "app-entity-bulk-actions",
templateUrl: "./entity-bulk-actions.component.html",
styleUrls: ["./entity-bulk-actions.component.scss"],
standalone: true,
imports: [
MatButtonModule,
ReactiveFormsModule,
BasicAutocompleteComponent,
...BASIC_AUTOCOMPLETE_COMPONENT_IMPORTS,
],
})
export class EntityBulkActionsComponent {
/**
* List of selected entities for bulk actions
*/
entities = input.required<Entity[]>();
private isExecutingAction = false;
/**
* Event emitted when the bulk action mode should be exited
* after an action was executed or the user cancelled the bulk actions.
*/
resetBulkActionMode = output();
private readonly actionsService = inject(EntityActionsMenuService);
/**
* Available bulk actions for the current selection
*/
bulkActions = resource({
params: () => ({ entities: this.entities() }),
loader: async ({ params }) => {
const bulkActions = await this.actionsService.getActionsForBulk(
params.entities,
);
return bulkActions
.map((action) => {
if (action.action === "merge") {
return {
...action,
disabled: !this.entities() || this.entities().length !== 2,
};
}
return action;
})
.filter((action) => !!action);
},
defaultValue: [],
});
actionControl = new FormControl();
actionToString = (action: EntityAction) => action?.label || "";
constructor() {
this.actionControl.valueChanges.subscribe((action) => {
if (action) this.onActionSelected(action);
});
// Enable/disable actionControl based on entities selection
effect(() => {
const entities = this.entities();
if (!entities || entities.length === 0) {
this.actionControl.disable({ emitEvent: false });
} else {
this.actionControl.enable({ emitEvent: false });
}
});
}
async onActionSelected(action: EntityAction) {
if (this.isExecutingAction) {
return;
}
this.isExecutingAction = true;
if (action && typeof action.execute === "function") {
await action.execute(this.entities());
}
this.resetBulkActionMode.emit();
this.actionControl.setValue(null, { emitEvent: false });
this.isExecutingAction = false;
}
cancel() {
this.resetBulkActionMode.emit();
}
}
<div class="flex-row gap-regular overall-box">
<div class="bulk-action-select-wrapper">
<mat-form-field class="bulk-action-autocomplete full-width">
<mat-label i18n>Select Bulk Action</mat-label>
<app-basic-autocomplete
[formControl]="actionControl"
[options]="bulkActions.value()"
[optionToString]="actionToString"
display="text"
></app-basic-autocomplete>
@if (!entities() || entities().length === 0) {
<mat-hint i18n>
Please select one or more rows to enable bulk actions.
</mat-hint>
} @else {
<mat-hint i18n>
Action will execute on {{ entities().length }} selected records.
</mat-hint>
}
</mat-form-field>
</div>
<button mat-raised-button (click)="cancel()" i18n>Cancel</button>
</div>
./entity-bulk-actions.component.scss
@use "@angular/material/core/style/elevation" as mat-elevation;
.overall-box {
@include mat-elevation.elevation(3);
padding: 1em;
margin: 1em;
}
.bulk-action-select-wrapper {
position: relative;
flex: 1 1 0%;
min-width: 320px;
max-width: 700px;
width: 400px; /* Fixed width for stability */
}
.bulk-action-autocomplete {
/* remove form-field bottom spacing */
margin-bottom: 0;
}
.bulk-action-autocomplete.full-width {
width: 100%;
min-width: 0;
max-width: 100%;
box-sizing: border-box;
}