Tutorial

03. Customize resources

AdminJS works quite well with a default scaffolding, but what if you want to modify how the Resources look like? You can use ResourceOptions

Resource options

ResourceOptions are passed to the AdminJS along with other configuration options.

...
const Article = require('./models/article')

const adminJsOptions = {
  resources: [
    { resource: Article, options: {
       // ...your options go here
    }},
  ],
  branding: {
    companyName: 'Amazing c.o.',
  },
  ...
}
...

AdminJS will use defaults setting whey you wont pass any options.

How a Resource can be modified?

You have lots of options. You can modify the basic appearance of a resource and more complicated aspects, as to how a particular field should be rendered.

In the next sections, I will point out a couple of options. For the full list visit the ResourceOptions interface.

{ parent } In the sidebar

By default AdminJS groups resources by the database, they belong to. But you can change that and group them in a different way. It can be done by using a parent option.

So let say you want to group all text'ish resources into a content category in the sidebar. You can do this by passing the parent as an option:

const contentParent = {
  name: 'content',
  icon: 'Accessibility',
}
const adminJsOptions = {
  resources: [
    { resource: Article, options: { parent: contentParent } },
    { resource: BlogPost, options: { parent: contentParent } },
    { resource: Comment, options: { parent: contentParent } },
  ],
}

This will group all Resources together in a "Content" category in a sidebar - and it assigns Accessibility icon to it. Shat you give here is passed to Icon Component.

As you see we passed name: 'content' but AdminJS changed that to 'Content'. This is because, by default, all texts are "Start Cased".

You can provide any translation text to it by using translation label: see tutorial 09. Internationalization (i18n).

Renaming a Resource

By default - the name of a Resource is taken from the database collection/table - you can change that by setting a i18n label

const adminJsOptions = {
  resources: [
    { resource: Article, options: {...} },
  ], 
  locale: {
    translations: {
      labels: {
        Article: 'Amazing Article'
      }
    }
  },
}

Take a look at tutorial: 09. Internationalization (i18n) and read more about internationalization in AdminJS.

{ xxxProperties } - visibility of properties

It defines which properties should be visible in a list, edit, show and filter views.

Let's say that you have a resource city with 20 fields like name, lat, lng, population, pollution, .... By default AdminJS will render first DEFAULT_MAX_ITEMS_IN_LIST which is 8. What if you want to present just 3 of them in a different order.

You can do this by using listProperties option:

const adminJsOptions = {
  resources: [
    { resource: City, options: { listProperties: ['name', 'population', 'polution'] } },
  ],
}

The same goes with showProperties, editProperties and filterProperties.

{ properties[propertyName] } - custom property options

AdminJS allows you to:

  • fully customize how each property should be presented
  • add custom properties

Everything thanks to PropertyOptions.

Visibility of properties { ...[propertyName].position } and { ...[propertyName].isVisible }

using xxxProperties is not the only way of handling which property should be seen on a list, edit, filter and show views. You can achieve a similar result by using position and isVisible options.

Using them have more sense if you want to disable one particular field, so instead of modifying entire xxxProperties array you can set up just one filed.

In the following example, I will hide name field in the list, filter and the edit, but will leave it in a show view.

const adminJsOptions = {
  resources: [
    { resource: City, options: { properties: {
      name: {
        isVisible: { list: false, filter: false, show: true, edit: false },
      }
    }},
  ],
}

You can hide an entire field from all views by simply setting isVisible to false.

Also, you can simply change the position of a field by using position option. By default all fields have position 100, except the title field which gets position -1 - means it will be at the beginning of a list.

Important notice about overriding xxxProperties: both { propertyName.position } and { propertyName.isVisible } will be overwritten by xxxProperties if you set it.

{ [propertyName].isTitle }

As I mentioned a title property goes first in the list of all properties, and in smaller screens, only this property stays. Also title property is the property on which you can search in autocomplete (by default).

AdminJS tries to pick title property automatically. It is property with name "name" or "email". You can change this behavior by setting PropertyOptions#isTitle for default property to false and for the new property to true.

{ [propertyName].type } of a property

By default types of properties are computed by adapters, see tutorial: 02. Adding resources tutorial.

So when you have a DATE field it will be rendered as a date with DatePicker and custom from - to filter.

You can change this behavior by modifying its type. So, for instance, you can add a richtext editor to a content like that:

const adminJsOptions = {
  resources: [
    { resource: City, options: { properties: {
      content: { type: 'richtext' },
    }},
  ],
}

And you will see https://quilljs.com editor in place of a regular text field.

Supported types can be found here

{ [propertyName].availableValues } narrow down the possible values

when you pass this option to a property it will render the select HTML element with all the available options.

{
  ...
  name: 'genre',
  label: 'Genre'
  availableValues: [
    {value: 'male', label: 'Male'},
    {value: 'female', label: 'Female'},
  ],
  ...
}

{ [propertyName].components } property appearance

You can also totally change the way of how property is rendered. The only thing you have to do is to change components responsible for rendering given field.

So let say we want to change the way how content property is rendered on the list:

const adminJsOptions = {
  resources: [{
    resource: City,
    options: {
      properties: {
        content: {
          components: {
            list: AdminJS.bundle('./city-content-in-list'),
          },
        },
      },
    },
  }],
}
// city-content-in-list.jsx
import React from 'react'

const CityContentInList = (props) => (
  <div>Some custom content...</div>
)

export default CityContentInList

You can read more about creating your own components in this tutorial: 05. Writing your own Components.

Adding new properties

Also, you can add new properties to the Resource by using a { properties.propertyName }. You just need to define some or all components (list, view, edit, filter). For example, if you want to group 'lat' and 'lng' fields on the list and display them as a google map in a show view you can use something like this:

const adminJsOptions = {
  resources: [
    { resource: City, options: { properties: {
      lat: { isVisible: { list: false, show: false, edit: true, filter: true } },
      lng: { isVisible: { list: false, show: false, edit: true, filter: true } },
      map: {
        components: {
          show: AdminJS.bundle('./city-in-a-show'),
        },
        isVisible: {
          show: true, view: false, edit: false, filter: false,
        }
      },
    }},
  ],
}

Then you will have to create city-in-a-list.jsx react component (or .tsx for TypeScript). To see how to do this visit tutorial: 05. Writing your own Components.

What's next?

To see all available options - check out the

There is an another very important section in ResourceOptions - actions. It gives you the ability to modify existing actions like edit or delete or add new actions. Go to the next tutorial: 04. Customize actions to read more about them.

You can also read more about creating your own components in this tutorial: 05. Writing your own Components.