Accessing additional image properties in Custom Block Vue Component

Hi,

I have made a custom block which renders basically an image an some text. This block (TextImage.vue) is used in my headless frontend as well as inside kirby as a block. However, I noticed that in my frontend I am having a layout shift, which I wanted to solve by adding the width and height attribute to the image.
Sadly, the width and height attributes are not available as props in the vue component.

Is there any way to retrieve the width and height of the image and pass it to the vue component (and access it via this.content)?

As a workaround I tried to alter the name of the uploaded image to include the width and height - but that sadly messes with the thumbnail and the image path in the panel (otherwise, is there a way to at least fix that?).

Thank you!

I think the easiest way would be to (ab)use the info (or text) property of the files field. This information is then available to the Vue component, iirc.

Thank you for the quick response! Could you maybe elaborate on this a bit more? The thing is I don’t want the user to manually yet the width and height, I would rather just get it from the file when they upload (i.e. $image->width()).

I also tried to just change the values e.g. when the page changes via the hook (e.g. the user selects another image). But sadly what I experienced was that when uploading it Works, but it I just select an already uploaded image it would take the wrong image’s width (i.e. the previous one).

What I meant was inside your block yaml, put the information into the info option (or alternatively text). I’m not 100% sure this is passed on to the component, please check. If not, you would have to resort to making a custom API call.

fields:
  image:
    type: files
    info: "{{file.width}},{{file.height}}"

This worked! At least inside the panel I have the info now available.

Now, is there also a way to return all the info from the block as a json response? Currently I am returning the block data as follows:

foreach ($page->myPage()->toBlocks() as $block) {
  $data = array("type" => $block->type(), "data" => $block->content()->data());
}

However, for the image it only returns the image relative path and nothing else:

"image": [
  "myPage/foo-bar.png"
]

Is there a way to return also other infos in the json response?

You would have to configure the array of data you return manually. You could limit this by block type, i.e. if $block->type() is an image, you don’t simply return the content data, but the data you need.

$data = [];
foreach ($page->myPage()->toBlocks() as $block) {
  if ($block->type() === 'image') {
    $data[] = [
      'image'  => ($file = $block->image()->toFile()) ? $file->id() : null;
      'width'   =>  $file?->width(),
      'height' => $file?->height(),
    ];
  } else {
    $data[] = ['type' => $block->type(), 'data' => $block->content()->data()];
}

return $data;

(Code not tested, but you get the idea).

1 Like

Perfect, this works - exactly what I needed. Thank you very much!