Trouble getting multiselect text on 3.8

I’m having trouble getting the value of multiselect fields for a custom block preview after updating to 3.8.

I have a multiselect field (called size) for layout options, the blueprint is set up so the option value is what I can get on the front end for a class name, and the option text is what I show on the panel as an indicator of what styling the block is set to currently:

size:
    width: 1/2
    label: Block Layout
    type: multiselect
    options:
      width-33: 33%
      width-40: 40%
      width-50: 50%
      width-60: 60%
      width-100: 100%

Like so, how it used to look like on 3.7:

Except now on 3.8 I’m unable to access the field value/selected option(s) with .text as I used to before on a block preview plugin:

<li v-for="item in this.content.size">
  <span v-html="item.text"></span>
</li>

item returns the selected option’s value (width-50) for the multiselect, item.text returns nothing on 3.8. var_dump returns the same on both 3.7 and 3.8:

object(Kirby\Cms\Field)#300 (1) { ["size"]=> string(8) "width-50" } 

I saw that the multiselect fields were reworked on 3.8 so that the option value is not shown anymore on the panel but I can’t figure out how that should affect being able to get the value/text of the selected option separately. Am I doing something wrong? Am I missing something? Is this just how the multiselects are now?

(I’m somewhat of a newbie still, sorry if I’m missing something extremely obvious :sweat_smile:).

I wonder if that is because text and value are not explicitly defined in the field. There were some changes to how options are handled, and my assumption is that that might be the cause.

Since you make no difference between value and text, I guess simply changing fromitem.text to item solves the issue, if I understand you correctly?

I’ve tried writing the blueprint like so:

size:
    width: 1/2
    label: Block Layout
    type: multiselect
    options:
      - value: width-33
        text: 33%
      - value: width-40
         text: 40%
      - value: width-50
         text: 50%
      - value: width-60
         text: 60%
      - value: width-100
         text: 100%

and the same persists. I can’t access text for the preview.

Since you make no difference between value and text, I guess simply changing fromitem.text to item solves the issue, if I understand you correctly?

The examples I posted are the first options I have on the multiselect, further down I have more complex options where the value is more concise (so I can use them as CSS classes on the front end) but the text/option description is more complex (for example has-spacing: “More spacing below”). I can’t use the same text for both because part of the CSS comes from another project and rewriting the whole thing would take a like long, long time (trust me, I considered this before even posting about this).

I just want to be able to access the text and value of the multiselect separately.

Edit: calling just item returns width-50 aka the value of the option. For the block preview I need the text of the option, in this case 50%.

Hm, don’t know then. Maybe @distantnative can help out with this?

I’m only with my phone until Monday, but I think I could still narrow it down: we had a lot of escaping issues and issues where wrong stuff ended in content files for fields with options prior to 3.8. So we rewrote have the front end and backend communicate, always just exchanging the value now. That’s what you’re whitnessing.

Now the part which is speculating because I can’t test it right now. But maybe you could get hold of the blueprint options via this.fieldset or this.field(fieldname) - and find the multi select options in there. This would allow you to get the text for the selected value then.

Outputting this.field("size") with <span v-html="sizeField"></span> returns an array of the options but none of them have an indication of being the one currently selected:

{
  "autofocus": false,
  "default": [],
  "disabled": false,
  "label": "Block Layout",
  "name": "size",
  "options": [
    {
      "disabled": false,
      "icon": null,
      "info": null,
      "text": "33%",
      "value": "width-33"
    },
    {
      "disabled": false,
      "icon": null,
      "info": null,
      "text": "40%",
      "value": "width-40"
    },
    {
      "disabled": false,
      "icon": null,
      "info": null,
      "text": "50%",
      "value": "width-50"
    },
    {
      "disabled": false,
      "icon": null,
      "info": null,
      "text": "60%",
      "value": "width-60"
    },
    {
      "disabled": false,
      "icon": null,
      "info": null,
      "text": "100%",
      "value": "width-100"
    },
    
    // many more options here, too long and irrelevant to post, 
    // they look the same as the ones above with diff. values/text
  ],
  "required": false,
  "saveable": true,
  "search": true,
  "separator": ",",
  "signature": "b529a09e436bdd6ebab60db33df7d30c",
  "sort": false,
  "strict": true,
  "translate": true,
  "type": "multiselect",
  "value": [],
  "width": "1/2",
  "endpoints": {
    "field": "/pages/test/fields/blocks/fieldsets/text/fields/size",
    "section": "/pages/test/sections/fields",
    "model": "/pages/test"
  }
}

so I’m not sure how I would go about getting the text of selected option/options.

This is not time sensitive, I’ve just breaking my brain trying to figure out if I was the one doing the something wrong. If you can get back to me about this on Monday that would be great!

Correct it’s just the available options. But you mentioned that you get the currently selected value/s via item. So you can take these and
Look up the option with the matching value and take that one’s text.

I’m afraid I’m out my depth now. Not sure how I would do that. :sweat_smile:

Something like

options.find(option => option.value === item).text

Ok sweet, that worked! Thank you!

Here’s the solution in case anyone needs it in the future:

panel.plugin("public/text", {
  blocks: {
    text: {
      computed: {
        options() {
          return this.field("size").options;
        }
      },
      template:
      `
        <ul>
          <li v-for="item in this.content.size">
            <span v-html="options.find(option => option.value === item).text"></span>
          </li>
        </ul>
      `
    }
  }
});
2 Likes