Sorting Images from panel

Hello

I’m sorry I realise this has been asked before but I just don’t seem to be able to resolve my issue from what I have read on the forum.

I want to be able to sort images on the front end using the built in drag and drop on the panel I have seen that to do this I need to use

<?php $images = $page->images()->sortBy('sort', 'asc') ?> <?php foreach($images as $image): ?>

But this did not work so I then determined that I probably needed to have sortable: true for the image files. However I am not sure I am implementing this correctly.

Here are my Blueprints and Template code, where am I going wrong?

title: Exhibitions
icon: 📅

options:
  url: true
  status: true
  delete: true


columns:
  main:
    width: 2/3
    sections:
          drafts:
            extends: sections/exhibitions
            headline: Draft exhibitions
            status: draft
            sortBy: exhibitiontype asc dateadded desc
            info: "{{ page.exhibitiontype }} {{ page.dateadded.toDate('d.m.Y') }}"
          listed:
            type: pages
            extends: sections/exhibitions
            headline: Published exhibitions
            status: listed
            sortBy: exhibitiontype asc dateadded desc
            info: "{{ page.exhibitiontype }} {{ page.dateadded.toDate('d.m.Y') }}"
          
          unlisted:
            extends: sections/exhibitions
            headline: Hidden exhibitions
            status: unlisted
            sortBy: exhibitiontype asc dateadded desc
            info: "{{ page.exhibitiontype }} {{ page.dateadded.toDate('d.m.Y') }}"
          sectionimage:
            headline: Section Image (optional)
            type: files
            template: image
            max: 1
  sidebar:
    width: 1/3
    sections:
      listsettings:
        type: fields
        fields:
          introduction:
            label: Introduction
            help: Introduction to Exhibitions list
            type: textarea
            size: medium
          expandeditems:
            label: Number of items to expand with images
            type: number
            default: 0
            min: 0
            max: 10
            validate: 
              match: /([0-9])+$/i
          addsummary:
            label: Add summary of item text to expanded items
            type: toggle      

Image Template:

title: Image
accept:
  mime: image/jpeg, image/png
options:
  delete: 
    *: true
  replace: 
    *: true
  update: 
    *: true
sortable: true
maxsize: 2
fields:
  alt:
    label: Alt Text
    type: text
  title: 
    label: title
    type: text
  text:
    label: Add Image Text
    type: textarea
    size: small
  attribution:
    label: Attribute to
    type: text
  link_to:
    label: External link
    type: url
  tif_link:
    label: Link for tif
    type: url
  hiresjpeg_link:
    label: Link to hi res jpeg
    type: url

Image Gallery code:

<?= css('assets/css/gallery.css') ?>
<section class="gallery">
  <?php if($page->images()): ?>
    <?php $images = $page->images()->sortBy('sort', 'asc') ?>
    <?php foreach($images as $image): ?>
    <div class="item_image_container">
      <!--<a href="<?= $image->url() ?>">-->
        <img class="item_image" src="<?= $image->url() ?>" alt="<?= $image->alt() ?>" title="<?= $image->title() ?>" >
      <!--</a>-->
      <?php if($image->title() != ''): ?>
        <div class="image_title"><?= $image->title()->html()?></div>
      <?php endif ?>
      <?php if($image->attribution() != ''): ?>
        <div class="image_attribution">Photo: <?= $image->attribution()->html()?></div>
      <?php endif ?>
      <?php if($image->text() != ''): ?>
        <div class="image_text"><?= $image->text()->html()?></div>
      <?php endif ?>
      <?php if($image->tif_link()->text() != ''): ?>
        <a class='image_link' href="<?= $image->tif_link()->url() ?>"> Download tif file here</a>
      <?php endif ?>
      <?php if($image->hiresjpeg_link()->text() != ''): ?>
        <a class='image_link'  href="<?= $image->hiresjpeg_link()->url() ?>"> Download a high resolution JPEG file here</a>
      <?php endif ?>

    </div>
    <?php endforeach ?>
  <?php endif ?>
</section>

Content code which calls the gallery:

<?php snippet('header') ?>

<content>

<div class="cpad">

<div class="container">
  <div id="item">
    <div id="item_content">
    
      <div class="item_title">
        <h3><?= $page->title() ?></h3><br>
        <span class="dateline"><?php snippet('displaydate',['item' => $page]) ?></span>
      </div>
      
      <?php if($page->layout() == 'below'): ?>
        <?php snippet('gallery') ?>
        <span class="lede"><?= $page->introduction()->kirbytext() ?></span>
      <?php else: ?>
        <span class="lede"><?= $page->introduction()->kirbytext() ?></span>
        <?php snippet('gallery') ?>
      <?php endif ?>
     
     <!-- <div class="return_line">
        <p><span class="linkline"><a href="<?= $page->parent()->url() ?>">Return to the previous page</a></span></p>
      </div>-->
      
    </div>
</div>

Many thanks in anticipation

Have you sorted the images manually so they really have a sorting number? Unless I’ve missed something, I can’t see a files section with multiple files in your page blueprint?

Once you drag an image around, they all get a sorting number (check in the meta data files if that is the case).

Note that if you upload a new file, it does not automatically get a new sorting number, you will have to drag it somewhere for this to happen.

The Files section is in the Item Template

images:
type: files
sortable: true
template: image

Is the problem because I called this images with type files rather than files with label/headline ‘Images’

I have use drag and drop to re-arrange the images on the panel but I don’t see any numbering in the Meta Data files. Should I be adding a manual image number to the images ?

I hope that makes sense

No.

However, I wonder if you have defined a files field instead of a files section that stores the filenames in the content file of the page? If that is the case, you have to fetch the files from the content field and convert into a files object.

$images = $page->content()->images()->toFiles();
if ($images->isNotEmpty()) 
  foreach ($images as $image) {
    // do stuff
  }
}

(Note that it is advisable to name fields something other than native page methods…)

(Admittedly, the difference between a files section and a files field can be a bit tricky if you are new to Kirby).

Thanks Texnixe I will try this and read up about difference in Files Sections and files fields

oops - I discovered that in fact the template was ok just that I had incorrect indentation in the blueprint! All working now.

On a side note, your HTML is not valid, because a <span> tag may not contain flow content.

And this line

should be

if ($page->images()->isNotEmpty())

otherwise, the condition will always be true, because an empty collection is still a collection.

Also, I wonder if it wouldn’t make more sense to wrap the condition around the outer section to prevent an empty section tag in case there are no images. I suggest the following:

<?php $images = $page->images()->sortBy('sort', 'asc') ?>
<?php if ($images->isNotEmpty()) : ?>
  <section class="gallery">
    <?php foreach($images as $image): ?>
      <!-- rest of code -->
    <?php endforeach ?>
  </section>
<?php endif ?>

Thank you for this I have updated my code to reflect your suggestions.