Auto populate title field with content from other fields

I have a collection called listings with a title field that I don’t want to be editable in the admin. But each time a listing is saved, I want the title field to be updated with values from other fields.

For e.g. if a house has 4 bedrooms, 2 bathrooms, the listing ID is 1234 and the rent is $1600 a month, on save the title field would be: “ID 1234: 4 bed / 2 bath / 1600 a month”.

System Information
  • Strapi Version: 4.1.6
  • Operating System: OSX
  • Database: Sqlite
  • Node Version: 16.13.2
  • NPM Version: 8.5.4
  • Yarn Version: 1.22.18

You can extends the core controller when the house item create and update. when the created response, you can set title depends other args。or you also can rewrite the whole create/update controller.

I think this is the docs for this: Backend customization - Controllers - Strapi Developer Docs

So to achieve something like this, I would have to override the update action (screenshot attached)?

Any examples out there to show me how to retrieve the data from other fields? I guess I’m having trouble finding examples in the documentation. They are a bit vague.

@sumitpaul You can add next code to the file src/api/house/controllers/house.js (if you have this file, others you should find you own), You can have a try, if it doesn’t work, I will update a case to github GavinXue/strapi-study-cases: strapi use cases when study, maybe it can help someone else., You also can have a check late today.

'use strict';
const { createCoreController } = require('@strapi/strapi').factories;
const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::house.house', ({ strapi }) => ({
  async update(ctx) {
    const response = await super.update(ctx);

    // generate title
    const { bed, bath, rent } = response.data.attributes
    const generateTitle = `${bed} bed / ${bath} bath / ${rent} a month`

    // update title to database
    // method 1 (use update) also you can use other api to update title
    ctx.request.body.data = { title: generateTitle }
    const finalRes = await super.update(ctx)

    return finalRes
  }
}));

You may find the guide for the Slug System helpful. It essentially achieves what you are asking for, but unfortunately requires some view configuration in the admin console. At the time of this comment, the guide is written for v3. The paths referenced within do not exist in v4.

The slugify for v4 is now in plugin market https://market.strapi.io/plugins/strapi-plugin-slugify

@GavinXue I tried this, but it doesn’t seem to work. I’ll try diffing through the slugify plugin for clues. Thanks @jseashell

@sumitpaul Have you copy it to a create() function. The title should be effected by create and update. and I just put update.
just in case you will try again, you can clone the cases repo and run it to see the effects.
Hope slug will solve your problem.

I have some updates. I used lifecycle hooks and followed the documentation here: Models - Strapi Developer Docs

In src/api/house/content-types/house/lifecycles.js I added the following code:

module.exports = {
    beforeCreate(event) {
        const { data } = event.params;
        data.title = `${data.bed} bed / ${data.bath} bath / ${data.rent} USD a month`;
    },
    beforeUpdate(event) {
        const { data } = event.params;
        data.title = `${data.bed} bed / ${data.bath} bath / ${data.rent} USD a month`;
    }
}

What if I wanted to also extract something from a relation? For e.g. house_type, the problem is that right now if I do ${data.house_type} it returns an ID. How do I get the actual title from that relation?

Here’s what finally works the way I want it to. In my src/api/house/content-types/house/lifecycles.js:

module.exports = {
    async beforeCreate(event) {
        const { data } = event.params;
        
        const houseType = await strapi.db.query('api::house_type.house_type').findOne({
            where: { id: data.house_type }
        });

        data.title = `${data.bed} bed / ${data.bath} bath / ${houseType.name} / ${data.rent} USD a month`;
    },
    async beforeUpdate(event) {
        const { data } = event.params;

        const houseType = await strapi.db.query('api::house_type.house_type').findOne({
            where: { id: data.house_type }
        });

        data.title = `${data.bed} bed / ${data.bath} bath / ${houseType.name} / ${data.rent} USD a month`;
    }
}```