How to iterate through an image array within a custom block preview (index.js)

Hi there — I’m new to Kirby and just started to implement a custom block type following this tutorial.

My custom block features an upload field which allows to upload a bunch of images (pretty much like the original Gallery block).

In the block php I was able to access those images with:
$block->myCustomImages()->images()->toFiles() (is that the correct way?)

However I also want to display a preview of my images in the backend itself (using index.js). I know I can access them with {{ content.myCustomImages }} — but how can I iterate through those images so I can display them as thumbnails?

Bonus points if they would be displayed like the original Gallery block preview :pray:

Any help would be much appreciated.

Thanks, Martin

I think you can loop over it in a similar way to the gallery block which does it like this…

so content.images would be all the images belonging to that page.

1 Like

And this should be

`$block->myCustomImages()->toFiles()`
1 Like

Thanks everyone! I just tried to copy & paste the <template> part of the Gallery.vue file but without luck.

undefined is not an object (evaluating ‘content.images.length’)

Here’s what my index.js file (located at site/plugins/carousel) looks like:

panel.plugin("mrtn/carousel", {
  blocks: {
    carousel: {
      template: `
      <template>
        <figure>
          <ul @dblclick="open">
            <template v-if="content.images.length === 0">
              <li
                v-for="index in 5"
                :key="index"
                class="k-block-type-gallery-placeholder"
              >
                <k-aspect-ratio :ratio="ratio" />
              </li>
            </template>
            <template v-else>
              <li v-for="image in content.images" :key="image.id">
                <k-aspect-ratio :ratio="ratio" :cover="crop">
                  <img
                    :src="image.url"
                    :srcset="image.image.srcset"
                    :alt="image.alt"
                  />
                </k-aspect-ratio>
              </li>
            </template>
          </ul>
          <figcaption v-if="content.caption">
            <k-writer
              :inline="true"
              :marks="captionMarks"
              :value="content.caption"
              @input="$emit('update', { caption: $event })"
            />
          </figcaption>
        </figure>
      </template>
      `
    }
  }
});

What is your files field called? If it is not called images like in the gallery block, you have to adapt the field name.

1 Like

This was great advice, thank you @texnixe ! :smiling_face:

I thought I did use the correct value for myCustomImages but it turned out that in index.js everything has to be lowercased instead of camelCased? (I am using camelCase notation in the yml file — would that be considered as bad practice?)

No more errors for now but unfortunately still not the intended result. The panel now looks like this:

… on top the default gallery preview (the way I want it to be), below the one I tried to implement. Appreciate any help that leads me into the right direction :pray:

panel.plugin("mrtn/carousel", {
  blocks: {
    carousel: {
      computed: {
        captionMarks() {
          return this.field("caption", { marks: true }).marks;
        },
        crop() {
          return this.content.crop || false;
        },
        ratio() {
          return this.content.ratio || false;
        }
      },
      template: `
      <template>
        <figure>
          <ul @dblclick="open">
            <template v-if="content.carouselimages.length === 0">
              <li
                v-for="index in 5"
                :key="index"
                class="k-block-type-gallery-placeholder"
              >
                <k-aspect-ratio :ratio="ratio" />
              </li>
            </template>
            <template v-else>
              <li v-for="image in content.carouselimages" :key="image.id">
                <k-aspect-ratio :ratio="ratio" :cover="crop">
                  <img
                    :src="image.url"
                    :srcset="image.image.srcset"
                    :alt="image.alt"
                  />
                </k-aspect-ratio>
              </li>
            </template>
          </ul>
          <figcaption v-if="content.caption">
            <k-writer
              :inline="true"
              :marks="captionMarks"
              :value="content.caption"
              @input="$emit('update', { caption: $event })"
            />
          </figcaption>
        </figure>
      </template>
      `
    }
  }
});

Looks like the styles are missing

Any hints where to put these? It’s not mentioned in the tutorial linked above (I’m not using Vue). Adding it to index.js does not have any effect (or more likely: I am doing something wrong).

Well, you are using Vue (but not single file components), but if you don’t bundle, the styles go into a separate file, see: To bundle or not to bundle: differences of creating plugins with or without a build process | Kirby CMS

1 Like

This article was exactly what I needed to get it work — beyond helpful! — thank you so much @texnixe :clap: I really appreciate your support! Sorry for being such a n00b :upside_down_face:

Don’t worry, we were all there.

1 Like