Get selected values from a Select field within a Structure

I have this blueprint setup:

  locations:
    label: Addresses
    type: structure
    fields:
      district:
        type: select
        options:
          prenzlauerBerg: Prenzlauer Berg
          kreuzberg: Kreuzberg
          mitte: Mitte
          friedrichshain: Friedrichshain
          neukoelln: Neukölln
          ...

I would like to have a ‘select’ dropdown field in the frontend that is populated by only selected options from the content file, not all options from the blueprint.

        <select name="district" id="district">
            <option value="all">All</option>
            <option value="prenzlauerBerg">Prenzlauer Berg</option>
            <option value="mitte">Mitte</option>
        </select>

What’s the best way to do this? As far as I understand, pluck cannot do this. I have a category-map setup for dealing with the output strings.

You can’t select more than one value in a select field. Are you looking for Multiselect?

you would do something like this:

<select name="district" id="district">
    <option value="all">All</option>
    <?php foreach ($page->district()->split() as $district(): ?>
        <option value="<?= $district; ?>"><?= $district; ?></option>
    <?php endforeach; ?>
</select>

Pluck can do that, at least from a single page. If you want all selected options from all pages, you need a custom method.

Sorry, I should’ve clarified: I have multiple pages that use this blueprint and would like the select value from each of the pages.

Oh, sorry, that’s a different story. But @pixelijn is right, pluck could do this. In a custom method, you would pluck all values from the pages and push them into an array which you then return.

Sounds about right. I’m new to custom method’s though. Would it be something similar to this?

That is old Kirby 2 code, please check the docs: https://getkirby.com/docs/reference/plugins/extensions/pages-methods

1 Like

Thanks! This seems to work…

<?php
Kirby::plugin('my/pagesMethods', [
    'pagesMethods' => [
        'selectStructure' => function ($pages) {
            $districts = [];
            foreach($pages as $page) {
                $district = $page->locations()->toStructure()->pluck('district',',',true);
                array_push($districts, $district);
            }
            return $districts;
        }
    ]
]);

In controller:

$districts = $places->selectStructure($places);

In template:

<select name="district" id="district">
    <option value="all">All</option>
    <?php foreach ($districts as $district): ?>
        <?php foreach ($district as $d): ?>
            <option value="<?= $d ?>"><?= option('category-map')[$d] ?></option>
        <?php endforeach ?>
    <?php endforeach ?>
</select>

Although this works for my specific case, how would I go about making it more reusable? At the moment it looks for specific fields by name, is there a way I can get it to just look for a select field within a structure regardless of its name? @pixelijn @bruno

Yes, but that would mean reading the blueprint ($page->blueprint()).

The content files don’t store information about their content “type”. For that you’d have to load the blueprint and work through that. (like pixelijn wrote)

You could however add some attributes to your method and tell it what fields it should use:

<?php
Kirby::plugin('my/pagesMethods', [
    'pagesMethods' => [
        'structurePluck' => function ($structure, $field) {
            $values = [];
            foreach($this as $page) { // $this refers to the $pages collection you are calling the method on
                $value = $page->{$structure}()->toStructure()->pluck($field,',',true);
                array_push($values, $value);
            }
            return $values;
        }
    ]
]);

use it like this:
$districts = $places->structurePluck('location', 'district');

1 Like

This is great, thank you!

I have another question related to this. I’m using this function to flatten the array:

function array_flatten($array) {
    $return = array();
    foreach ($array as $key => $value) {
        if (is_array($value)){ $return = array_merge($return, array_flatten($value));}
        else {$return[$key] = $value;}
    }
    return $return;
  }

I’ve added these lines to the pagesMethod to flatten and remove duplicates:

$values = array_flatten($values);
$values = array_unique($values);

I tried to include the array_flatten function in the pagesMethod itself, but this doesn’t seem to work. Storing it in the controller works, but I may want to use this on multiple pages and don’t want to have to add the function to every controller that uses structurePluck.

Where can I store this function so it’s more reusable?