You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -47,12 +47,66 @@ Here's how to add a custom action:
47
47
-`name`: Display name of the action
48
48
-`icon`: Icon to show (using Flowbite icon set)
49
49
-`allowed`: Function to control access to the action
50
-
-`action`: Handler function that executes when action is triggered
50
+
-`action`: Handler function that executes when action is triggered for a **single** record
51
+
-`bulkHandler`: Handler function that executes when the action is triggered for **multiple** records at once (see [Bulk button with bulkHandler](#bulk-button-with-bulkhandler))
51
52
-`showIn`: Controls where the action appears
52
-
-`list`: whether to show in list view
53
-
-`listThreeDotsMenu`: whether to show in three dots menu in the list view
54
-
-`showButton`: whether to show as a button on show view
55
-
-`showThreeDotsMenu`: when to show in the three-dots menu of show view
53
+
-`list`: whether to show as an icon button per row in the list view
54
+
-`listThreeDotsMenu`: whether to show in the three-dots menu per row in the list view
55
+
-`showButton`: whether to show as a button on the show view
56
+
-`showThreeDotsMenu`: whether to show in the three-dots menu of the show view
57
+
-`bulkButton`: whether to show as a bulk action button when rows are selected
58
+
59
+
### Bulk button with `action`
60
+
61
+
When `showIn.bulkButton` is `true` and only `action` (not `bulkHandler`) is defined, AdminForth automatically calls your `action` function **once per selected record** using `Promise.all`. This is convenient for simple cases but means N separate handler invocations run in parallel:
62
+
63
+
```ts title="./resources/apartments.ts"
64
+
{
65
+
name: 'Auto submit',
66
+
action: async ({ recordId }) => {
67
+
// Called once per selected record when used as a bulk button
68
+
awaitdoSomething(recordId);
69
+
return { ok: true, successMessage: 'Done' };
70
+
},
71
+
showIn: {
72
+
bulkButton: true, // triggers Promise.all over selected records
73
+
showButton: true,
74
+
}
75
+
}
76
+
```
77
+
78
+
If your operation can be expressed more efficiently as a single batched query (e.g., a single `UPDATE … WHERE id IN (…)`), define `bulkHandler` instead. AdminForth will call it **once** with all selected record IDs:
79
+
80
+
```ts title="./resources/apartments.ts"
81
+
{
82
+
name: 'Auto submit',
83
+
// bulkHandler receives all recordIds in one call – use it for batched operations
// You can still keep `action` for the single-record show/edit buttons
89
+
action: async ({ recordId }) => {
90
+
awaitdoSomething(recordId);
91
+
return { ok: true, successMessage: 'Done' };
92
+
},
93
+
showIn: {
94
+
bulkButton: true,
95
+
showButton: true,
96
+
}
97
+
}
98
+
```
99
+
100
+
> ☝️ When both `action` and `bulkHandler` are defined, AdminForth uses `bulkHandler` for bulk operations and `action` for single-record operations. When only `action` is defined and `bulkButton` is enabled, AdminForth falls back to `Promise.all` over individual `action` calls.
101
+
102
+
### Bulk-specific options
103
+
104
+
| Option | Type | Description |
105
+
|---|---|---|
106
+
|`showIn.bulkButton`|`boolean`| Show as a bulk action button in the list toolbar. |
107
+
|`bulkHandler`|`async ({ recordIds, adminUser, adminforth, resource, response, tr }) => { ok, error?, message? }`| Called with all selected IDs at once. Falls back to calling `action` per record in parallel if omitted. |
108
+
|`bulkConfirmationMessage`|`string`| Confirmation dialog text shown before the bulk action executes. |
109
+
|`bulkSuccessMessage`|`string`| Success message shown after the bulk operation. Defaults to `"N out of M items processed successfully"`. |
56
110
57
111
### Access Control
58
112
@@ -84,46 +138,11 @@ The `allowed` function receives:
84
138
Return:
85
139
-`true` to allow access
86
140
-`false` to deny access
87
-
- A string with an error message to explain why access was denied
141
+
- A string with an error message to explain why access was denied — e.g. `return 'Only superadmins can perform this action'`
88
142
89
143
Here is how it looks:
90
144

91
145
92
-
93
-
You might want to allow only certain users to perform your custom bulk action.
94
-
95
-
To implement this limitation use `allowed`:
96
-
97
-
If you want to prohibit the use of bulk action for user, you can do it this way:
Instead of defining an `action` handler, you can specify a `url` that the user will be redirected to when clicking the action button:
@@ -146,7 +165,7 @@ The URL can be:
146
165
- A relative path within your admin panel (starting with '/')
147
166
- An absolute URL (starting with 'http://' or 'https://')
148
167
149
-
To open the URL in a new tab, add `?target=_blank`to the URL:
168
+
To open the URL in a new tab, append `target=_blank`as a query parameter. If the URL already has query parameters, use `&target=_blank`; otherwise use `?target=_blank`:
150
169
151
170
```ts
152
171
{
@@ -162,118 +181,12 @@ To open the URL in a new tab, add `?target=_blank` to the URL:
162
181
163
182
> ☝️ Note: You cannot specify both `action` and `url` for the same action - only one should be used.
164
183
165
-
166
-
167
-
## Custom bulk actions
168
-
169
-
You might need to give admin users a feature to perform same action on multiple records at once.
170
-
171
-
For example you might want allow setting `listed` field to `false` for multiple apartment records at once.
172
-
173
-
AdminForth by default provides a checkbox in first column of the list view for this purposes.
174
-
175
-
By default AdminForth provides only one bulk action `delete` which allows to delete multiple records at once
176
-
(if deletion for records available by [resource.options.allowedActions](/docs/api/Back/interfaces/ResourceOptions/#allowedactions))
177
-
178
-
To add custom bulk action quickly:
179
-
180
-
```ts title="./resources/apartments.ts"
181
-
//diff-add
182
-
import { AdminUser } from'adminforth';
183
-
//diff-add
184
-
import { admin } from'../index';
185
-
186
-
{
187
-
...
188
-
resourceId: 'aparts',
189
-
...
190
-
options: {
191
-
//diff-add
192
-
bulkActions: [
193
-
//diff-add
194
-
{
195
-
//diff-add
196
-
label: 'Mark as listed',
197
-
//diff-add
198
-
icon: 'flowbite:eye-solid',
199
-
//diff-add
200
-
// if optional `confirm` is provided, user will be asked to confirm action
201
-
//diff-add
202
-
confirm: 'Are you sure you want to mark all selected apartments as listed?',
const stmt =admin.resource('aparts').dataConnector.client.prepare(`UPDATE apartments SET listed = 1 WHERE id IN (${selectedIds.map(() =>'?').join(',')})`);
Action code is called on the server side only and allowed to only authorized users.
222
-
223
-
> ☝️ AdminForth provides no way to update the data, it is your responsibility to manage the data by selectedIds. You can use any ORM system
224
-
> or write raw queries to update the data.
225
-
226
-
> ☝️ You can use `adminUser` object to check whether user is allowed to perform bulk action
227
-
228
-
229
-
> Action response can return optional `successMessage` property which will be shown to user after action is performed. If this property is not provided, no messages will be shown to user.
230
-
231
-
Here is how it looks:
232
-

233
-
234
-
235
-
## Limiting access to bulk actions
236
-
237
-
You might want to allow only certain users to perform your custom bulk action.
238
-
239
-
To implement this limitation use `allowed`:
240
-
241
-
If you want to prohibit the use of bulk action for user, you can do it this way:
const stmt =admin.resource('aparts').dataConnector.client.prepare(`UPDATE apartments SET listed = 1 WHERE id IN (${selectedIds.map(() =>'?').join(',')}`);
Copy file name to clipboardExpand all lines: adminforth/documentation/docs/tutorial/03-Customization/10-menuConfiguration.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -275,7 +275,7 @@ auth: {
275
275
276
276
```
277
277
278
-
This syntax can be use to get unique avatar for each user of hardcode avatar, but it makes more sense to use it with [upload plugin](https://adminforth.dev/docs/tutorial/Plugins/upload/#using-plugin-for-uploading-avatar)
278
+
This syntax can be use to get unique avatar for each user of hardcode avatar, but it makes more sense to use it with [upload plugin](https://adminforth.dev/docs/tutorial/Plugins/05-0-upload/#using-plugin-for-uploading-avatar)
0 commit comments