Skip to main content

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:

./schema.prisma
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:

./resources/realtors.ts
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:

./resources/realtorsAparts.ts
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:

./index.ts

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:

./resources/apartments.ts
import Many2ManyPlugin from '@adminforth/many2many';

...

plugins: [
...

new Many2ManyPlugin({
linkedResourceId: 'realtors',
})

...
]

...

The plugin is set up. Create some records in the realtors table: alt text Now, when creating an apartment, you can select (link) one or more realtors. alt text After saving the record, rows in the junction table are created automatically: alt text

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
})

...