Skip to content

Relations

strapi2front provides full support for Strapi relations, including the advanced relation API introduced in Strapi v5.

Strapi supports several relation types:

TypeDescriptionTypeScript
oneToOneSingle relation, single targetAuthor | undefined
manyToOneMultiple sources, single targetCategory | undefined
oneToManySingle source, multiple targetsComment[] | undefined
manyToManyMultiple sources, multiple targetsTag[] | undefined

Relations must be explicitly populated to be included in responses:

// Without population - relations are undefined
const article = await articleService.findOne("abc123");
console.log(article.author); // undefined
// With population - relations are loaded
const article = await articleService.findOne("abc123", {
populate: ["author", "categories"],
});
console.log(article.author); // { id: 1, name: "John", ... }

Load nested relations:

const article = await articleService.findOne("abc123", {
populate: {
author: {
populate: ["avatar", "company"],
},
categories: {
fields: ["name", "slug"],
},
},
});

The simplest way to set relations is using document IDs:

// Single relation
await articleService.create({
title: "New Article",
author: "authorDocumentId",
});
// Multiple relations
await articleService.create({
title: "New Article",
categories: ["cat1", "cat2", "cat3"],
});

Enable advanced relations in your config:

strapi.config.ts
schemaOptions: {
advancedRelations: true,
}

Add relations while preserving existing ones:

await articleService.update("abc123", {
categories: {
connect: ["newCat1", "newCat2"],
},
});

Remove specific relations:

await articleService.update("abc123", {
categories: {
disconnect: ["catToRemove"],
},
});

Replace all relations (removes existing, adds new):

await articleService.update("abc123", {
categories: {
set: ["onlyCat1", "onlyCat2"],
},
});
await articleService.update("abc123", {
categories: {
connect: ["newCat"],
disconnect: ["oldCat"],
},
});

Control the order of relations using position:

// Add after specific item
await articleService.update("abc123", {
categories: {
connect: [{
documentId: "newCat",
position: { after: "existingCat" },
}],
},
});

Connect to specific localized versions:

await articleService.update("abc123", {
relatedArticles: {
connect: [{
documentId: "relatedId",
locale: "es", // Connect to Spanish version
}],
},
});

Connect to specific publication states:

await articleService.update("abc123", {
relatedArticles: {
connect: [{
documentId: "relatedId",
status: "published", // Only connect to published version
}],
},
});
// Connect to draft version
await articleService.update("abc123", {
relatedArticles: {
connect: [{
documentId: "draftId",
status: "draft",
}],
},
});

Complete example with all advanced relation features:

await articleService.update("abc123", {
// Replace all tags
tags: {
set: ["tag1", "tag2", "tag3"],
},
// Modify categories (connect + disconnect)
categories: {
connect: [
{ documentId: "newCat", position: { start: true } },
{ documentId: "anotherCat", position: { after: "newCat" } },
],
disconnect: ["oldCat"],
},
// Connect to localized content
relatedArticles: {
connect: [
{ documentId: "spanishArticle", locale: "es" },
{ documentId: "publishedOnly", status: "published" },
],
},
});

With advanced relations enabled, your forms can handle complex relation updates:

function EditArticleCategories({ article, allCategories }) {
const form = useForm({
resolver: zodResolver(articleUpdateSchema),
defaultValues: {
categories: article.categories?.map(c => c.documentId) || [],
},
});
const onSubmit = async (data) => {
const currentIds = article.categories?.map(c => c.documentId) || [];
const newIds = data.categories;
// Calculate connect/disconnect
const toConnect = newIds.filter(id => !currentIds.includes(id));
const toDisconnect = currentIds.filter(id => !newIds.includes(id));
await articleService.update(article.documentId, {
categories: {
connect: toConnect,
disconnect: toDisconnect,
},
});
};
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
{/* Multi-select for categories */}
</form>
);
}
FeatureStrapi v4Strapi v5
Simple relationsid or [id]documentId or [documentId]
Connect/DisconnectLimitedFull support
Position orderingNoYes
i18n in relationsNoYes
Status in relationsNoYes

strapi2front generates appropriate schemas based on your Strapi version.