Relationship dropdown edit widget filter - how to filter dataset based on current entity

With the following scenario:

  • You organize Concerts
  • Concerts have Bands
  • Concerts also have BandMembers
  • Bands have BandMembers

As such there is a one-to-many relationship between a Concert and Bands, and between a Band and BandMembers, and between a Concert and BandMembers.

Bands and BandMembers don’t live outside of Concerts.
(I couldn’t think of a better example. It makes sense in our data)

Feature(s) impacted

One-to-many field editing.

Observed behavior

When editing a one-to-many field, every possible foreign entity is listed, even if it makes no sense.

In that case, editing a BandMember’s Band will list every single Band of every Concert, even if the BandMember’s Band is in another Concert!

Expected behavior

It should be possible to filter the dropdown to only show Bands which are in the BandMember’s Concert.

Either via a UI help like selecting sub-fields of relationships, or maybe via a specific notation:
Concept screenshot

Context

I have found How can i filter my dropdown from relation? but I was hoping there was a nicer way to do this using the provided widget settings. Fingers crossed!

  • Agent type & version: 8.3.3
1 Like

Hello @kll,

Thanks for reaching out!

If I understood well your use case, there is unfortunately no way to fix this in the UI.
However, it should be doable and not too complicated to do it in the code, overriding your GET route to band and using the request.query.context.

Something like this:

router.get('/bands', permissionMiddlewareCreator.list(), async (request, response, next) => {
  if (request.query.context.record.type === 'bandMember') {
    const bandMember = await bandMembers.findByPk(request.query.context.record.id, {
      include: [ { model: concerts, attributes: ['id'] } ]
    });
    const bandMemberConcertIds = band.concerts.map(concert => concert.id);

    const foundBands = await bands.findAll({
      where: {
        concertId: { [Op.in]: bandMemberConcertIds }
      }
    });
    const serializer = new RecordSerializer(bands, request.user, request.query);
    response.send(await serializer.serialize(foundBands));
  } else {
    next();
  }
});

Let me know if this helps!
Thanks.

1 Like

Hey @anon34731316!

With a couple tweaks here and there to fit our TypeScript backend, this fit amazingly.
It’s in production now. Thank you very much!

Is there any documentation somewhere about the record object and what we may expect it to contain? It looks very useful.

1 Like

Well no, I don’t think it is documented.
It actually depends on the request, you can always have a look to the payload to see what it contains :slightly_smiling_face:

Cheers!

@anon34731316 Hey again! I think it would be great to actually document it, since after upgrading to 8.3.3 the field is no longer type but collection and, in our case, it’s the PascalCased name of the collection instead of the kebab-case collection type.

Blame’s on me for using undocumented features, but this is a tremendously useful one in many scenarios.

Mh, it seems the API is actually different depending on the field type being edited? The old solution still works in this case (one-to-many edit), but couldn’t be applied in a different relationship

Hey @kll,

As this topic was solved months ago, could you please open a new thread so that it could be tackled properly?

Thanks!