Skip to main content

Standard pages tuning

Fields Grouping

In some cases, you may want to organize data fields into specific groups for better structure and clarity. For example, you could create a "Main Info" group to include columns like title, description, country, and apartment_image. Another group, "Characteristics," could hold attributes such as price, square_meter, number_of_rooms, property_type, and listed. Any values without a specified group will be categorized under "Other.

./resources/apartments.ts
export default {
...
options: {
...
fieldGroups: [
{
groupName: 'Main info',
columns: ['id','title', 'description', 'country', 'apartment_image']
},
{
groupName: 'Characteristics',
columns: ['price', 'square_meter', 'number_of_rooms', "property_type", "listed"]
}
],
}
}

Here is how it looks: alt text

You can also specify on which page you want to create or delete groups. If you assign null, the groups will disappear from this page.

./resources/apartments.ts
export default {
...
options: {
createFieldGroups: [
{
groupName: 'Main info',
columns: ['id','title']
},
{
groupName: 'Characteristics',
columns: ['description', 'country', 'price', 'square_meter', 'number_of_rooms', "property_type", "listed"]
}
],
editFieldGroups: null,
showFieldGroups: null,
}
}

List

Default Sorting

./resources/apartments.ts
import { AdminForthSortDirections } from 'adminforth';

...
export default {
resourceId: 'aparts',
options: {
defaultSort: {
columnName: 'created_at',
direction: AdminForthSortDirections.asc,
}
}
}

Page size

use options.listPageSize to define how many records will be shown on the page

./resources/apartments.ts
export default {
resourceId: 'aparts',
options: {
...
listPageSize: 10,
}
}
]

Custom row click action

By default, when you click on a record in the list view, the show view will be opened.

You can change this behavior by using options.listTableClickUrl.

To disable any action (don't open show) return null:

./resources/apartments.ts
export default {
resourceId: 'aparts',
options: {
...
listTableClickUrl: async (record, adminUser) => null,
}
}
]

To open a custom page, return URL to the custom page (can start with https://, or relative adminforth path):

./resources/apartments.ts
      options: {
...
listTableClickUrl: async (record, adminUser) => {
return `https://google.com/search?q=${record.name}`;
}
}

If you wish to open the page in a new tab, add target=_blank get param to the returned URL:

./resources/apartments.ts
      options: {
...
listTableClickUrl: async (record, adminUser) => {
return `https://google.com/search?q=${record.name}&target=_blank`;
}
}

Auto-refresh records

options.listRowsAutoRefreshSeconds might be used to silently refresh records that are loaded (no new records will be fetched if they appear)

./resources/apartments.ts
export default {
resourceId: 'aparts',
hooks: {
list: {
afterDatasourceResponse: async ({ response }: { response: any }) => {
response.forEach((r: any) => {
// substitute random country on any load
const countries = [ 'US', 'DE', 'FR', 'GB', 'NL', 'IT', 'ES', 'DK', 'PL', 'UA',
'CA', 'AU', 'BR', 'JP', 'CN', 'IN', 'KR', 'TR', 'MX', 'ID']
r.country = countries[Math.floor(Math.random() * countries.length)];
})
return { ok: true, error: "" }
}
}
},
options: {
...
listRowsAutoRefreshSeconds: 1,
}
}
]

alt text

Creating

Fill with default values

Sometimes you want to generate some field value without asking user to fill it. For example createdAt oftenly store time of creation of the record. You can do this by using fillOnCreate:

./resources/apartments.ts

export default {
name: 'apartments',
fields: [
...
{
name: 'created_at',
type: AdminForthDataTypes.DATETIME,
fillOnCreate: ({ initialRecord, adminUser }) => (new Date()).toISOString(),
},
],
},
...
],

Also you can assign adminUser ID by adminUser.dbUser.id in same hook:

./resources/apartments.ts
export default {
name: 'apartments',
fields: [
...
{
name: 'created_by',
type: AdminForthDataTypes.STRING,
fillOnCreate: ({ initialRecord, adminUser }) => adminUser.dbUser.id,
},
],
},
...
],

Same effect can be achieved by using hooks. But fillOnCreate might be shorter and more readable.

Sometimes you might need to create a link that will open the create form with some fields pre-filled. For example, you might want to create a link that will open the create form with the realtor_id field pre-filled with the current user's ID.

<template>
...
<LinkButton
:to="{
name: 'resource-create',
params: {
resourceId: 'aparts',
},
query: {
values: encodeURIComponent(JSON.stringify({
realtor_id: coreStore?.adminUser.dbUser.id
})),
},
}"
>
Create new apartment
</LinkButton>
...
</template>

<script setup lang="ts">
import { LinkButton } from '@afcl';
import { useCoreStore } from '@/stores/core';

const coreStore = useCoreStore();
</script>

Editing

You can set a column editReadonly so it will be shown in the edit form but will be disabled.
This might be useful to better identify the record during editing or to show some additional information that should not be changed but can help to edit the record.

./resources/apartments.ts
export default {
name: 'apartments',
fields: [
...
{
name: 'created_at',
type: AdminForthDataTypes.DATETIME,
editReadonly: true,
},
],
},
...
],