# Resources
A "resource" means a given server entity which can be managed by Vuetify Admin, i.e. created/read/updated/deleted. It must correspond to a valid API endpoint that allows all of this CRUD operations.
The next piece of code represent an example of expected structure that must be sent to Vuetify Admin constructor as seen previously :
src/resources/index.js
export default [
{
name: "users",
icon: "mdi-account",
label: "name",
routes: ["list"],
permissions: ["admin"],
},
{
name: "monsters",
icon: "mdi-alien",
label: "name",
translatable: true,
permissions: ["admin", "parent"],
},
{
name: "monster_children",
icon: "mdi-baby-carriage",
label: "name",
except: ["delete"],
},
];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Resource object structure
A resource object must follow this structure :
Property | Type | Description |
---|---|---|
name | string | A mandatory unique slug name which will be used for client-side router base path. |
api | string | Correspond to API base path calls. Equal to above name by default. |
icon | string | A identifier icon in sidebar or list page, should be a valid MDI (opens new window). |
label | string , function | Return the target property that identify an instantiated resource (toString ). |
include | array , object | Some additional object or array that will be added to data providers for all GET based methods for further actions inside data provider. |
routes | array | List of available routes for this resource. All available by default. |
actions | array | List of valid actions for this resource. All available by default. |
except | array | Denied actions, not used if actions is explicitly set. |
translatable | boolean | Indicates if this resource can be translated. |
permissions | array | Enable resource according to user permissions, as shown here. |
autocompleteFields | array | List of resource fields to return from API inside VaAutocompleteInput for avoiding over-fetching. |
LABEL
The label
property can take a string or function, and is equal to label
by default. Use string for simple case which represents a valid property of the targeted resource, as name
for a users
resource. Using a function, which is a simple callback that takes the full resource API object, allows you to return more complex combination of properties, as (r) => `${r.title} (${r.isbn})`
.
This label will be used for default page title for every show and edit CRUD pages as well as every reference-based fields and inputs (VaReferenceField
, VaReferenceArrayField
, VaAutocompleteInput
, VaSelectInput
, VaRadioGroupInput
).
ACTIONS
For actions, you have to choose between list
/ show
/ create
/ edit
/ delete
. If none actions
or except
is set, all 5 operations are active by default.
All removed actions will be reflected on all crud pages and Vue Router will be adapted accordingly as well. For example, if you set except
to ["show"]
, it will disable show
route and all show
actions (mainly buttons) associates to the concerned resource.
DISABLING ACTIONS
Note that it will only disable routes client-side generation and change action buttons behavior. The resource API module has always all actions method available. Adapt your backend accordingly for prevent any unintended actions.
# Reuse API endpoints
You can perfectly reuse the same backend resource api endpoint for different resources. Imagine a first group of cruds pages that show only active resources and a separate second group of cruds pages that show only archived ones.
Use the api
property for that. It will override API default base path in resource store module. Then every CRUD pages inside src/resources/{name-1}
and src/resources/{name-2}
will use the same API endpoint.
See this example :
export default [
{
name: "users",
icon: "mdi-account",
label: "name",
routes: ["list"],
permissions: ["admin"],
},
{
name: "archived_users",
api: "users",
icon: "mdi-account",
label: "name",
routes: ["list"],
permissions: ["admin"],
},
];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
The archived_users
resource will reuse the same API endpoints as users
resource.
# Resource CRUD pages and API modules
With the above resources information, it's enough for Vuetify Admin to recreate all necessary CRUD routes and API actions structures.
Each CRUD route search for a component named as ${ResourceName}${Action}
, both on StudlyCase
. 4 action pages are supported : List
, Show
, Create
and Edit
. So for a given resource called monsters
and for a create
route, VA search for a MonstersCreate
page component. If not found it fallbacks to a copyable guesser page. All you have to do is to register all your CRUD resources pages with this component naming convention in mind.
In order to facilitate this boring task, use the provided loader to do this automatically by importing it with import "vuetify-admin/src/loader"
. It will search for all vue
files inside src/resources
directory and register them to main Vue instance by given a proper component name. With this loader, you just have to create one vue component for each action inside a resource folder which will take the slugged name of resource.
Example for a monster_children
and users
resources :
resources
├── monster-children
(The kebab-case format of resource slug or name)
│ ├── Create.vue
│ ├── Edit.vue
│ ├── Form.vue (Form component reused for both Create and Edit views)
│ ├── List.vue
│ └── Show.vue
│
├── users
(No need of Create or Edit here as we use direct list aside feature for this)
│ ├── Form.vue
│ ├── List.vue
│ └── Show.vue
│
└── index.js
(Resources file descriptor as seen above)
COMPOUND NAME
If the name resource is a compound format, use a hyphen between each word (this is the kebab-case format). Example monster-children
for a resource named as monster_children
.
# Action mapping
Some quick tables to resume (we take monster_children
resource name as example).
# Action route and API mapping
Action | Vue Route | API call format |
---|---|---|
list | /monster-children | GET /monster_children |
show | /monster-children/{id} | GET /monster_children/{id} |
create | /monster-children/create | POST /monster_children |
edit | /monster-children/{id}/edit | PUT /monster_children/{id} |
delete | - | DELETE /monster_children/{id} |
# Action component mapping
Action | Page Component | Path from src/resources |
---|---|---|
list | MonsterChildrenList | /monster-children/List.vue |
show | MonsterChildrenShow | /monster-children/Show.vue |
create | MonsterChildrenCreate | /monster-children/Create.vue |
edit | MonsterChildrenEdit | /monster-children/Edit.vue |
# Injected props
On every CRUD pages, the following props will be injected for easy reuse :
Action | Type | Path from src/resources |
---|---|---|
resource | object | The resource object descriptor linked to the current route. |
title | string | The localized title of resource action page. |
id | id | ID of current resource to be displayed or edited. |
item | object | Current item to be displayed, edited or cloned. |
permissions | array | Current user permissions. |
To use it, you simply have to declare them on props page component :
<script>
export default {
props: ["resource", "title", "item"],
};
</script>
2
3
4
5
# Link helpers
You may need to put some links through your app that point to list or create resource pages, mainly in the sidebar. For that you can use getResourceLink
and getResourceLinks
helpers that will build for you a working link object that follow this format. Moreover, this helpers will test the current users permissions for this specific action of this resource. If failed, it returns false.
For example this piece of code will return a link object to the user page list with localized resource label as well as resource icon. Simply put this function in any valid layout menu props as it was a link object. No need to deal with permissions or adding nulling test since a false menu will simply not be rendered.
[
//...
this.$admin.getResourceLink("users"),
//...
]
2
3
4
5
Use getResourceLinks
in order to make many resource links at once. Only links where users has the resource action permissions will be returned.
[
//...
...this.$admin.getResourceLinks([
"publishers",
"authors",
"books",
"reviews",
]),
//...
]
2
3
4
5
6
7
8
9
10
For this helpers, you can pass a full link object instead of resource name that will override the default generated. For example this code will generate a new link to the user create page with a plus icon and a "Create new user" as text :
[
//...
this.$admin.getResourceLink({ name: "users", action: "create", icon: "mdi-plus", text: "Create new user" }),
//...
]
2
3
4
5
The getResourceLinks
helper can accept hierarchical menu as following :
[
//...
...admin.getResourceLinks([
{
icon: "mdi-globe-model",
text: "Publishers,
expanded: true,
children: [
admin.getResourceLink({ name: "publishers", icon: "mdi-view-list", text: "List" }),
admin.getResourceLink({ name: "publishers", icon: "mdi-plus", text: "Create" }),
],
},
"authors",
"books",
"reviews",
]),
//...
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18