Render Key/Values from dynamic checkbox or select fields

As far as I understand (and experience) - if I use a field like this:

        params:
          label: Params
          type: select
          options: query
          query: 
            #fetch: site.find("downloads/gasket-parameters").children()
            fetch: kirby.collection("gasket-parameters")
            text: "{{ page.title }}"
            value: "{{ page.id }}"

the value gets saved (in the above case the field page.id) and in my template I have to pull in the blueprint to show the text or better title of my selection. But since options is set to query I also have to parse the fetch: kirby.collection("gasket-parameters") value myself. Correct?

There is no magic that does that for me? Same for Checkboxes, right?


Only if you really need the information from the blueprint. Why do you need the collection information?

You would get the page like this:

// convert to page object
$p = $pages->params()->toPage();
echo $p->title();

Getting the text property from the blueprint wouldn’t make much sense, because that would only return the string "{{ page.title }}".

Thank you! toPage() worked, but that assumes, that for this collection a page object exists, right?
(I already messed around with new Query() :roll_eyes:

What about the example with the external json API

category:
  label: Category
  type: checkboxes
  options: api
  api: "https://your-options-api.com/options.json"

Is it the same?

The above was the lazy version. Of course, you always have to make sure that you have a (page) object:

if ( $p = $pages->params()->toPage() ) {
  echo $p->title();
}

That depends what your json API returns. If you return a set of page ids, you can create pages from these ids, if they return a set of files, you can create files from the data. But of course not, if you just returns anything.

ok, so I use this field definition (the endpoint works):

        category:
          label: Category
          type: checkboxes
          options: api
          api:
            url: https://run.mocky.io/v3/9b3e1cf6-41d2-4bdc-b1e5-30abefdee859
            fetch: Companies
            text: "{{ item.text }}"
            value: "{{ item.value }}"

The Endpoint outputs this:

{
  "Companies": [
    {
      "value": "apple",
      "text": "Apple",
      "extra": "iphone"
    },
    {
      "value": "intel",
      "text": "Intel",
      "extra": "chip"
    },
    {
      "value": "microsoft",
      "text": "Microsoft",
      "extra": "OS"
    }
  ]
}

In the panel it will be rendered like this:

image

And my selection is saved like this:

----

Category: apple, intel

----

And in my template I would access it like this:

$page->category()->??

I couldn’t identify a field method that would parse the api: properties. I did find the OptionsApi class https://github.com/getkirby/kirby/blob/master/src/Form/OptionsApi.php, that’s being called to process the field definition in the backend, I believe - and that deals with the remote api request etc.

How do I get this working in the frontend?

Each field (should) have a section about how to use in templates.

yes, in that case the example is just splitting the comma separated list :confused:

A checkboxes field stores all selected values in a comma separated list ( value1, value2, value3 ) You can split this list with the split() method in your templates and then work with the result:

image

Hm, what is it that you wanted to achieve here?

Ok, I updated my example: Render Key/Values from dynamic checkbox or select fields

What I want ist render my selection (Apple and Intel) in the frontend.

I’d use a custom method that fetches the data from the URL and returns the required value. Or your store the text instead of the value in the field, so you don’t have to convert anything. Depending on your data, simple string manipulation could also do the job.

Thanks for the advice. So in conclusion there is no build-in way to easily use the data from the API. I definitely have to fetch it again in a custom method.

What I found works, and I fear it’s a bit convoluted (saving the text instead the values is indeed easier :)) is a fieldMethod $field->options() based on this https://github.com/getkirby/kirby/blob/master/src/Form/Options.php#L105

<?php
use Kirby\Toolkit\A;
use Kirby\Form\Options;
use Kirby\Toolkit\Collection;

Kirby::plugin('mo/misc', [
	/**
	 * Field Methods
	 * @see https://getkirby.com/docs/reference/plugins/extensions/field-methods
	 */
	'fieldMethods' => [

		'options' => function ($data)
		{
			$field = $data->model()->blueprint()->field($data->key());
			$values = $data->split();

			$options = Options::factory(
				A::get($field, 'options'),
				$field,
				$data->model()
			);

			$collection = new Collection($options);

			return $collection->filterBy('value', 'in', $data->split());

		}
	]
]);

This is a blade template, but you’ll get the gist

@foreach($page->category()->options() as $category)
   {{ $category['text'] }} - {{ $category['value'] }}<br>
@endforeach

Have to experiment further. I learned a lot so far. Thanks!

Yes, at least if this data is not stored anywhere. What magic could Kirby possibly use to get your data, unless you store it somewhere (e.g. store the text and value instead of just then value, then you don’t have to query that data again)?

That was poorly worded - you are right, I have to request the remote json anyway, it’s not cached (unless I write it in my custom method).

I just noticed, since my fieldMethod uses the internal Options::factory it should render all option fields… (talking to myself here :))

$page->options_field()->options()