Query structure field but keep all fields

I know the title is not very good but let me try and explain what I’m trying to do: I have a structure field where I want to define all kinds of topics:

topics:
  label: Topics
  type: structure
  fields:
    title:
      label: Text
      type: text
    info:
      label: Info
      type: writer

Down below I have another structure field where sections are created and in each section I want to be able to use a multiselect field to select the relevant topics:

topics:
  label: Topics
  type: multiselect
  options:
    type: query
    query: page.topics.toStructure
    text: "{{ item.title }}"
    value: "{{ item.title }} {{ item.info }}"

So far so good, however on my page I would like to use the title and info field from the topics structure seperately like below so that I can create an accordion or anything similar

<?php foreach($solution->topics()->split(',') as $topic) : ?>
    <h2><?= $topic->title() ?></h2>
    <p><?= $topic->info()->inline() ?></p>
<?php endforeach; ?>

What would be the best way to achieve this? $topic returns a single string containing {{ item.title }} {{ item.info }} in the way I’ve set it up now.

I think you have two options here:

  1. only store the title as value, and get the info from the main topics structure using findBy()
  2. Store info and title like you do now, but use a separator (e.g. a pipe character, a semicolon or whatever, in any case some character not contained in text or info) to separate title from info, then split the value the by this character.

I’d even go one step further and use a third key field in the main structure, and store this key as value in the fields that query this structure. The key should not change. That way, you can modify typos or so in the title and info fields in the main structure, and these changes would be reflected in the referencing fields.

Or better still, instead of the structure field for the topics, consider using a blocks field with a custom block type. Blocks come with ids out of the box and you could then store these ids, and find the related block by this id.

The custom block seems te right option here. I’ve added the field like this:

topics:
  label: Topics
  type: blocks
  fieldsets:
    - topic

and added a custom topic block:

name: topic
fields:
  title:
    label: Title
    type: text
  info:
    label: info
    type: writer

My multiselectfield looks like this

topics:
  label: Topics
  type: multiselect
  options:
    type: query
    query: page.topics.toBlocks
    text: " {{ item.title }}"
    value: "{{ item.id }}"

So that I can get the ID of the selected topics like this:

<?php foreach($solution->topics()->toBlocks() as $topicID) : ?>
    <?= $topicID ?>
<?php endforeach; ?>

But how can I get the right topic? Something like
<?= $page->topics()->toBlocks()->findByKey($topicID)->title() ?>
Is not working. (I know the naming with the two topics is not ideal here). What should I do here?

Could you explain what you are trying to do here? What does $solution refer to? We are at the multiselect now and from the value store there, you want to get the corresponding block.

So how do I get to the multiselect?

Then I can help you from there…

Yes sorry so the multiselect is also inside a structure field in a foreach loop above:

<?php foreach($page->solutions()->toStructure() as $solution): ?>

Ok, so you don’t want to loop through the blocks at that point but fetch the block with the given id(s).

<?php foreach($page->solutions()->toStructure() as $solution): ?>
<?php
// loop through all block ids stored in the topics field of the solution item
foreach($solution->topics()->split() as $topicId) {
  // and foreach id, we want to find the corresponding block
  $block = $page->topics()->toBlocks()->findBy('id', $topicId);
  // if we have a block, echo its fields
  if (!is_null($block) {
    echo $block->title();
    echo $block->info();
  }
}
?>
<?php endforeach ?>

Thanks a lot!:raised_hands: Have a nice Sunday eve:)