Multiselect field choices not saving after page exit

Hi. I have a multiselect field in my homepage blueprint. It queries the list of customer quotations on the testimonials page. The field works correctly in that it lets me choose multiple items from the query…

If I save the page and then refresh the front-end, the selected content displays as intended. But when I exit the homepage in the Panel, and then go back, the multiselect field is empty. The saved choices haven’t saved.

The blueprint code looks as follows. (The ‘quotes’ section is the relevant part.)

- width: 2/3
	sections:
		main:
			type: fields
			fields:
				bannerhdl:
					label: Banner content
					type: blocks
					fieldsets:
						- text
						- button
						- markdown
				text:
					label: Body content
					type: blocks
				quotes:
					label: Selected testimonials
					type: multiselect
					options: query
					query:
						fetch: site.find("testimonials").testimonials.toStructure
						text: "{{ structureItem.customer }} ({{ structureItem.car }})"
						value: "{{ structureItem.quotation }} {{ structureItem.customer }}, who bought a {{ structureItem.car }}"
				cta:
					label: Call to action
					type: blocks
					fieldsets:
						- text
						- button
						- markdown

Am I missing something?

Thanks.

It probably happens because of the comma you are storing. If you really need that, and storing a simple value is not enough, use another separator for the entries, see docs for multiselect field.

If I were you, I’d give those structure items a unique key (either manually, via a hook, or via the AutoId plugin), store that value, and then fetch the other information via the stored key). That way, you can change the other fields in the structure and you output in the frontend will stay in sync with those changes.

Thanks for the reply, Sonja.

I tried removing the comma but that made no difference. In fact, I removed the brackets as well from the text: attribute, but still no joy. I save the page in the Panel, then refresh the front-end and the correct content appears on the webpage. But as soon as I refresh the Panel page, the selected multiselect items disappear.

What I’ve discovered, though, is that even though the multiselect items disappear from the Panel view, they remain in the home.txt content file. But if I then make other changes to the page and save again with the multiselect empty, it does clear the items from the content file.

I can’t understand why my multiselect selections are not staying in place. When I remove all the punctuation from the text: and value: attributes, my blueprint is exactly the same format as in the Multiselect documentation in the Kirby reference guide.

I did look at the AutoID plugin’s wiki and I’m not clear on how I’d set that up. It looks like the autoid: attribute is added as a hidden additional structure field – one autoid: per structure? If that’s right, how do I then get unique IDs for each structure item? I’m not clear how to implement this.

Thanks again

Adam

What is your Kirby version? Do you have a standard single language site or is it a multi-lang installation?

Can you see any errors happen in the console?

Could you also please post the revised multiselect field definition, or ideally the complete home.yml template?

Kirby version 3.9.4 running locally on XAMPP with PHP 8.1.2. Single language.

I do see one error in the console. Something to do with a label’s ‘for’ element and the violating node is the “Selected testimonials” label for the multiselect field. I assume that’s the issue because it says it might prevent the browser from autofilling the form. Not sure how to fix, though. This is the error…

And this is the entire home.yml…

title: Home

status:
	draft: Draft
	listed: Published

options:
	changeStatus: false

tabs:
	content:
		icon: text
		columns:

			- width: 2/3
				sections:
					main:
						type: fields
						fields:
							bannerhdl:
								label: Banner content
								type: blocks
								fieldsets:
									- text
									- button
									- markdown
							text:
								label: Body content
								type: blocks
							quotes:
								label: Selected testimonials
								type: multiselect
								options: query
								query:
									fetch: site.find("testimonials").testimonials.toStructure
									text: "{{ structureItem.customer }} {{ structureItem.car }}"
									value: "{{ structureItem.quotation }} {{ structureItem.customer }} {{ structureItem.car }}"
							cta:
								label: Call to action
								type: blocks
								fieldsets:
									- text
									- button
									- markdown

			- width: 1/3
				sections:
					hero:
						type: fields
						fields:
							bannerimg:
								label: Banner image
								type: files
								query: page.images
								max: 1
								layout: cards
								image:
									cover: true
									ratio: 16/9
									back: white
							carbadge:
								label: COTW badge
								type: toggle
								text:
									- "No"
									- "Yes"
							carlink:
								label: COTW page
								type: select
								options:
									type: query
									query: site.find('buy').children.published
								when:
									carbadge: true
					files:
						type: files
						image:
							cover: true
							back: white

	seotab: seo

I wanna try this out myself tonight, tbh I think I’ve always only used it with one value query.
If you keep tackling this in the meantime, does it make a difference if you also have no spaces in the value?

Please try if you run into the same issue if you just store a single value, e.g. the customer

              quotes:
                label: Selected testimonials
                type: multiselect
                options: query
                query:
                  fetch: site.find("test").testimonials.toStructure
                  text: "{{ item.customer }} {{ item.car }}"
                  value: "{{ item.customer }}"

(Note that you don’t have to differentiate between different types of items (structureItem, arrayItem) anymore, but the old names will still work)

Thanks for your suggestions, both.

@texnixe, your suggestion did work in that only a single value seems to be accepted. But I also discovered that not all of my structure items are accepted. For example, {{ item.customer }} works but {{ item.quotation }} does not. I also spotted that the resulting list in the front-end is comma separated. All of that poses a challenge for me.

To fully explain the context here, the structure field appears on the Testimonials page. It captures five pieces of information and, of course, the quotation itself is one of those…

testimonials:
    label: Testimonials
    type: structure
    columns:
        quotation:
            width: 1/2
        customer:
            width: 1/4
        car:
            width: 1/4
    fields:
        quotation:
            type: writer
            size: small
        customer:
            type: text
            width: 1/2
        hometown:
            type: text
            width: 1/2
        car:
            label: Car purchased
            type: text
            width: 1/2
        page:
            label: Car details page
            type: 
            type: select
            options:
                type: query
                query: site.children.published
            width: 1/2

That works perfectly on the Testimonials page. But I then want the client to be able to select from the list of testimonials to display in a carousel/slider on the homepage. So I chose the multiselect field with the query. The idea is that the client chooses which individual testimonials to display and then the quotation, the customer name and the car they bought are returned in the carousal.

But if I can only put one item in the value element, and quotation isn’t one of them, how can I populate the carousel? (The frustrating thing is that I’ve seen all the elements displayed on the homepage but the Panel page wouldn’t save.)

Is the multiselect field not the best option to use for this? Any other suggestions?

Many thanks.

Well, the idea is to store a one or multiple unique values. Then in the frontend, the first thing you have to do is split the comma-separated values into an array. then you loop through this array and find the structure item for this unique value. Then you read all the fields from this structure item.

That’s why I would set up the structure field either with a UUID from the above-mentioned plugin, or you add an addtional field like quotation_key or whatever, where you then add some value, maybe just something simple like quotation-1, quotation-2 etc.

This value should then be used to store the selected item in the multiselect field, so in your content field you would get for example:

Quotes: quotation-1, quotation-3, quotation-5

In the home template:

<?php

// convert comma separated list to array
$quotes = $page->quotes()->split(',');

// loop through array values
foreach ($quotes as $quote) {
  // try to find structure field item
  if ($item = page('testimonials')->toStructure()->findBy('quotation_key', $quote)) {
   // echo the different fields of the item
    echo $item->customer() . ' bought a ' .  $item->car();
  }
}

Hope you get the idea.

@texnixe. Thanks for your suggestion, Sonja, and apologies for the delayed response.

I’ve agreed with the client that we’ll go live with the site next week without the homepage carousel and I’ll add that as soon as I can post-launch. So, I’ll be coming back to your suggestion next week and might have one or two more questions as I work through it. Watch this space!

Thanks again for your continued support.