# 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"],
  },
];
1
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"],
  },
];
1
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>
1
2
3
4
5

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"),
  //...
]
1
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",
  ]),
  //...
]
1
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" }),
  //...
]
1
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",
  ]),
  //...
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18