Many2Many
This plugin lets you manage many-to-many relationships.
Installation
Install the plugin:
npm i @adminforth/many2many
Setting up
Let's say we want to implement a relationship where every apartment can have many realtors and each realtor can have many apartments. We'll also need a junction resource to connect realtors and apartments.
First, create the realtors table and the junction table realtorsAparts:
model realtors {
id String @id
name String
surname String
}
model realtorsAparts {
id String @id
realtorId String
apartmentId String
}
Migrate the Prisma schema:
npm run makemigration -- --name add-realtors-and-realtorsAparts; npm run migrate:local
Now create a resource for the realtors:
import { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth';
export default {
dataSource: 'maindb',
table: 'realtors',
resourceId: 'realtors',
label: 'Realtors',
recordLabel: (r) => ` ${r.name}`,
columns: [
{
name: 'id',
type: AdminForthDataTypes.STRING,
label: 'Identifier',
showIn: {
list: false,
edit: false,
create: false,
},
primaryKey: true,
fillOnCreate: ({ initialRecord, adminUser }) => Math.random().toString(36).substring(7),
},
{
name: 'name',
required: true,
showIn: { all: true },
type: AdminForthDataTypes.STRING,
maxLength: 255,
minLength: 3,
},
{
name: "surname",
required: true,
showIn: { all: true },
type: AdminForthDataTypes.STRING,
maxLength: 100,
minLength: 3,
}
],
options: {
listPageSize: 12,
allowedActions: {
edit: true,
delete: true,
show: true,
filter: true,
},
},
} as AdminForthResourceInput;
And one for the junction table realtorsAparts:
import { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth';
export default {
dataSource: 'maindb',
table: 'realtorsAparts',
resourceId: 'realtorsAparts',
label: 'Realtors-aparts',
columns: [
{
name: 'id',
type: AdminForthDataTypes.STRING,
label: 'Identifier',
showIn: {
list: false,
edit: false,
create: false,
},
primaryKey: true,
fillOnCreate: ({ initialRecord, adminUser }) => Math.random().toString(36).substring(7),
},
{
name: 'realtorId',
foreignResource: {
resourceId: 'realtors',
searchableFields: ['name'],
searchIsCaseSensitive: true
}
},
{
name: 'apartmentId',
foreignResource: {
resourceId: 'aparts',
searchableFields: ['title'],
searchIsCaseSensitive: true
}
},
],
options: {
listPageSize: 12,
allowedActions: {
edit: true,
delete: true,
show: true,
filter: true,
},
},
} as AdminForthResourceInput;
Now add the plugin resources to the main config file:
import realtorsResource from './resources/realtors.js';
import realtorsApartsResource from './resources/realtorsAparts.js';
...
dataSources: [
{
id: 'maindb',
url: `${process.env.DATABASE_URL}`
},
],
resources: [
...
realtorsResource,
realtorsApartsResource
]
...
menu: [
...
{
label: 'Realtors',
resourceId: 'realtors'
},
{
label: 'Realtors-aparts',
resourceId: 'realtorsAparts'
},
...
]
Finally, add the plugin to the apartments resource:
import Many2ManyPlugin from '@adminforth/many2many';
...
plugins: [
...
new Many2ManyPlugin({
linkedResourceId: 'realtors',
})
...
]
...
The plugin is set up. Create some records in the realtors table:
Now, when creating an apartment, you can select (link) one or more realtors.
After saving the record, rows in the junction table are created automatically:

Disable automatic cleanup of the junction table
By default, when you delete a realtor or an apartment, all related rows in the junction table are deleted automatically. To avoid this behavior, add:
...
new Many2ManyPlugin({
linkedResourceId: 'realtors',
dontDeleteJunctionRecords: true, // prevents automatic deletion of related junction rows
})
...