Outputting data

Hi there,

What’s the best way to output data as shown in the screenshot? Basically many different pictures with different titles above them? (sorry for not giving giving different titles and pictures in the screenshot).

Grateful for any tips.

Screenshot_20230914_203043

I would go with a structure field (Structure | Kirby CMS) if the images are not linked to subpages with more information.

1 Like

Many thanks for your feedback. This is looks really good.

You could also use the gallery block type. It displays the images nicely in the panel and you can add custom fields for each image using the files/image blueprint from the docs.

I’m trying to add extra fields to add different pictures and text above them as shown in the picture I posted. I copied this code:

type: pages
label: Products
parent: site.find("shop")
template: product
info: "€ {{ page.price }} / {{ page.design }}"
image:
  src: page.image
  ratio: 1/1
  back: pattern

from this page: Shop | Kirby CMS

and added it to the my existing yml file:

title: Betten
num: zero

status:
  draft: true
  listed: true

fields:
  Name:
    label: Produktname
    type: text

  Beschreibung:
    label: Beschreibung
    type: text

  Accordionbeschreibungeins:
    label: Produktinfos
    type: text

  Accordionbeschreibungzwei:
    label: Oberfläche
    type: text

  Accordionbeschreibungdrei:
    label: Accordion Beschreibung Nr. 3
    type: text

  Accordionbeschreibungvier:
    label: Accordion Beschreibung Nr. 4
    type: text

  files:
    label: Bilder
    type: files
    multiple: true # Allow multiple images
    template: image

type: pages
label: Products
parent: site.find("shop")
template: product
image:
  src: page.image
  ratio: 1/1
  back: pattern

No fields were added to the panel for the product category.

I’m trying to add the gallery to the yml file but it’s not showing in the panel:

title: Betten
num: zero

status:
  draft: true
  listed: true

fields:
  Name:
    label: Produktname
    type: text

  Beschreibung:
    label: Beschreibung
    type: text

  Accordionbeschreibungeins:
    label: Produktinfos
    type: text

  Accordionbeschreibungzwei:
    label: Oberfläche
    type: text

  Accordionbeschreibungdrei:
    label: Accordion Beschreibung Nr. 3
    type: text

  Accordionbeschreibungvier:
    label: Accordion Beschreibung Nr. 4
    type: text

  files:
    label: Bilder
    type: files
    template: image
    
  sidebar:
   gallery:
    type: files
    label: Gallery
    template: image

Grateful if you can point me in the right direction.

That did it and I thought I’d share it with you:

title: Betten
preset: page
num: zero

status:
  draft: true
  listed: true

fields:
  Name:
    label: Produktname
    type: text

  Beschreibung:
    label: Beschreibung
    type: text

  Accordionbeschreibungeins:
    label: Produktinfos
    type: text

  Accordionbeschreibungzwei:
    label: Oberfläche
    type: text

  Accordionbeschreibungdrei:
    label: Accordion Beschreibung Nr. 3
    type: text

  Accordionbeschreibungvier:
    label: Accordion Beschreibung Nr. 4
    type: text

  files:
    label: Produktbild
    type: files
    template: image
    
sidebar:
   gallery:
    type: files
    label: Gallery
    template: image

    

1 Like

Hi,

To create fields that will allow me to add fields for uploading images and entering title text above these images as shown in the screenshot, I put together this code:

title: Betten
preset: page
num: zero

status:
  draft: true
  listed: true

fields:
  Name:
    label: Produktname
    type: text

  Beschreibung:
    label: Beschreibung
    type: text

  Accordionbeschreibungeins:
    label: Produktinfos
    type: text

  Accordionbeschreibungzwei:
    label: Oberfläche
    type: text

  files:
    label: Produktbild
    type: files
    template: image

  paletteImages:
    label: Produkt-Palette Bilder
    type: files
    template: image

sidebar:
   gallery:
    type: files
    label: Gallery
    template: image

  tabs:

  # content tab
  content:
    label: Content
    icon: text
    preset: page
    fields:
      headline:
        label: Headline
        type: text
      text:
        label: Text
        type: textarea

However, I received two error messages: Invalid section type (“tabs”) and Invalid section type (“content”) in the panel. Attached is a screenshot.

Grateful for your guidance.

The error message says it for you: “tabs” is not a section type. You have nested your tabs under a section. Tabs should be the first level.

Hi, Thank you for your input. This did it, but I’m not sure if this is the correct way to do it:

title: Betten
preset: page
num: zero

status:
  draft: true
  listed: true

fields:
  Name:
    label: Produktname
    type: text

  Beschreibung:
    label: Beschreibung
    type: text

  Accordionbeschreibungeins:
    label: Produktinfos
    type: text

  Accordionbeschreibungzwei:
    label: Oberfläche
    type: text

  files:
    label: Produktbild
    type: files
    template: image

  TitleText1:
    label: Title Text 1
    type: text

  TitleText2:
    label: Title Text 2
    type: text

  TitleText3:
    label: Title Text 3
    type: text

  TitleText4:
    label: Title Text 4
    type: text

  TitleText5:
    label: Title Text 5
    type: text

  TitleText6:
    label: Title Text 6
    type: text

  TitleText7:
    label: Title Text 7
    type: text

  TitleText8:
    label: Title Text 8
    type: text

  TitleText9:
    label: Title Text 9
    type: text

  TitleText10:
    label: Title Text 10
    type: text

  TitleText11:
    label: Title Text 11
    type: text

  TitleText12:
    label: Title Text 12
    type: text

  TitleText13:
    label: Title Text 13
    type: text

  TitleText14:
    label: Title Text 14
    type: text

  TitleText15:
    label: Title Text 15
    type: text

  TitleText16:
    label: Title Text 16
    type: text

  TitleText17:
    label: Title Text 17
    type: text

  TitleText18:
    label: Title Text 18
    type: text

paletteImages:
  label: Produkt-Palette Bilder
  type: files
  template: image

sidebar:
  gallery:
    type: files
    label: Gallery
    template: image

Your use case really calls for a structure field as mentionned by stffr above.

structure:
  label: Structure with image and label
  type: structure
  fields:
    image:
      label: Image
      type: files
      layout: cards
      max: 1
    label:
      label: Label
      type: text
      default: Label

It would look like this in the panel:

See the docs here: Structure | Kirby CMS

1 Like

This is awesome. Thank you very much indeed.

According to this doc: Text | Kirby CMS , in order to output the value on the front end, I can put this in the template `

<?= $page->TitleText1() ?>

However, since the yml file looks like this, I don’t know how to output it correctly. This is from the template:

 <div class="image-container">
                                        <h3><?= $page->TitleText1() ->html() ?></h3>
                                            <img src="content/h0Vxgz5tyXA-unsplash.jpg">
                                        </div>

And this is the updated yml file:

title: Betten
preset: page
num: zero

status:
  draft: true
  listed: true

fields:
  Name:
    label: Produktname
    type: text

  Beschreibung:
    label: Beschreibung
    type: text

  Accordionbeschreibungeins:
    label: Produktinfos
    type: text

  Accordionbeschreibungzwei:
    label: Oberfläche
    type: text

  files:
    label: Produktbild
    type: files
    template: image

 structure:
  label: Structure with image and label
  type: structure
  fields:
    image:
      label: Image
      type: files
      layout: cards
      max: 1
    label:
      label: Label
      type: text
      default: Label

This is from the template:

                            <div class="accordion-body">
                                
                                <!-- ======= Product Palette  ======= -->

                                <?php if ($page->paletteImages()->isNotEmpty()) : ?>
                                    <div class="product-palette">
                                        <?php foreach ($page->paletteImages()->toFiles() as $image) : ?>
                                            <div class="palette-box">
                                                <div class="image-container">
                                                    <h3><?= $page->TitleText1() ?></h3>
                                                    <img src="<?= $image->url() ?>">
                                                </div>
                                            </div>
                                        <?php endforeach ?>
                                    </div>
                                <?php endif ?>
                            </div>

You should try to read the docs to the end. For each field type, there are clear examples of how to use the field in the templates.
I copied the snippet from the documentation and modified it for your blueprint:

<?php
// using the `toStructure()` method, we create a structure collection
$items = $page->structure()->toStructure();
// we can then loop through the entries and render the individual fields
foreach ($items as $item): ?>
  <div class="palette-box">
        <div class="image-container">
            <h3><?= $item->label()->html() ?></h3>
            <img src="<?= $item->image()->toFile()->url() ?>">
        </div>
    </div>
<?php endforeach ?>
1 Like

Many thanks for your guidance. I’ll go through the docs again and try to understand them better.
I think the reason why the values are not being outputted is because the modal slideshow is in JavaScript/ jQuery.

This is the betten.php template:

<?php snippet('header') ?>

<!-- ======= Introduction ======= -->

<div class="main-container">
    <main>
        <h1>Lorem ipsum dolor sit amet consectetur adipisicing elit.</h1>
        <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Qui voluptas provident nostrum velit incidunt. Quia mollitia cumque praesentium assumenda exercitationem quo inventore, voluptates harum saepe, vel, in quasi ratione amet?
        </p>
    </main>
</div>

<!-- ======= Products No. 2 ======= -->

<article class="beds">
    <?php if ($p = page('betten')) : ?>
        <?php foreach ($p->children()->limit(26) as $betten) : ?>
            <div class="beds-box">
                <!-- Add data attributes to store image, name, and description -->
                <a href="#" class="popup-trigger" data-image="<?= $betten->image()->url() ?>" data-name="<?= $betten->title()->html() ?>" data-beschreibung="<?= $betten->beschreibung()->html() ?>" data-accordionbeschreibungeins="<?= $betten->accordionbeschreibungeins()->html() ?>" data-accordionbeschreibungzwei="<?= $betten->accordionbeschreibungzwei()->html() ?>">
                    <?php if ($image = $betten->image()) : ?>
                        <img src="<?= $image->url() ?>" class="clickable-image">
                    <?php endif ?>
                </a>
                <div class="beds-box-title">
                    <h3><?= $betten->title()->html() ?></h3>
                </div>
            </div>
        <?php endforeach ?>
    <?php endif ?>
</article>


<!-- Adds the modal HTML structure -->

<div id="myModal" class="popupSlider">
    <span class="closeButton" id="closeSlider">&times;</span>
    <div class="slider-Content">
        <span class="arrow leftArrow" id="prevSlide">&#10094;</span>
        <span class="arrow rightArrow" id="nextSlide">&#10095;</span>

        <!-- ======= Single ======= -->

        <div class="single-product">
            <div class="the-product">
                <img id="popup-image" src="" alt="Popup Image" class="slida">
            </div>
            <div class="product-description">
                <ul class="breadcrumb">
                    <?php foreach ($site->breadcrumb() as $crumb) : ?>
                        <li<?php e($crumb->isActive(), ' aria-current="location"') ?>><a href="<?= $crumb->url() ?>"><?= $crumb->title()->html() ?></a></li>
                        <?php endforeach; ?>
                </ul>
                <h4 id="popup-name"></h4>
                <p id="popup-beschreibung"></p>

                <!-- ======= Bootstrap Accordion ======= -->

                <div class="accordion accordion-flush" id="accordionFlushExample">

                    <!-- Accordion 1 -->

                    <div class="accordion-item">
                        <h2 class="accordion-header" id="flush-headingOne">
                            <button class="accordion-button collapsed bold-accordion-header" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseOne" aria-expanded="false" aria-controls="flush-collapseOne">
                                Produktinfos
                            </button>
                        </h2>
                        <div id="flush-collapseOne" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#accordionFlushExample">
                            <div class="accordion-body"><span id="popup-accordionbeschreibungeins"></span></div>
                        </div>
                    </div>

                    <!-- Accordion 2 -->

                    <div class="accordion-item">
                        <h2 class="accordion-header" id="flush-headingTwo">
                            <button class="accordion-button collapsed bold-accordion-header" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseTwo" aria-expanded="false" aria-controls="flush-collapseTwo">
                                Oberfläche
                            </button>
                        </h2>
                        <div id="flush-collapseTwo" class="accordion-collapse collapse" aria-labelledby="flush-headingTwo" data-bs-parent="#accordionFlushExample">
                            <div class="accordion-body"><span id="popup-accordionbeschreibungzwei"></span></div>
                        </div>
                    </div>

                    <!-- Accordion 3 -->

                    <div class="accordion-item">
                        <h2 class="accordion-header" id="flush-headingThree">
                            <button class="accordion-button collapsed bold-accordion-header" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseThree" aria-expanded="false" aria-controls="flush-collapseThree">
                                Holzarten
                            </button>
                        </h2>
                        <div id="flush-collapseThree" class="accordion-collapse collapse" aria-labelledby="flush-headingThree" data-bs-parent="#accordionFlushExample">
                            <div class="accordion-body">

                                <!-- ======= Product Palette  ======= -->

                                <?php
                                // using the `toStructure()` method, we create a structure collection
                                $items = $page->structure()->toStructure();
                                // we can then loop through the entries and render the individual fields
                                foreach ($items as $item) : ?>
                                    <div class="palette-box">
                                        <div class="image-container">
                                            <h3><?= $item->label()->html() ?></h3>
                                            <img src="<?= $item->image()->toFile()->url() ?>">
                                        </div>
                                    </div>
                                <?php endforeach ?>
                            </div>
                        </div>
                    </div>

                    <!-- ======= Product Palette Stoffe ======= -->

                    <!-- Accordion 4 -->

                    <div class="accordion-item">
                        <h2 class="accordion-header" id="flush-headingFour">
                            <button class="accordion-button collapsed bold-accordion-header" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseFour" aria-expanded="false" aria-controls="flush-collapseFour">
                                Stoffe
                            </button>
                        </h2>
                        <div id="flush-collapseFour" class="accordion-collapse collapse" aria-labelledby="flush-headingFour" data-bs-parent="#accordionFlushExample">
                            <div class="accordion-body">

                                <!-- ======= Dropdown Palette ======= -->

                                <div class="product-palette">

                                    <div class="accordion-body">

                                        <!-- ======= Product Palette  ======= -->

                                        <?php
                                        // using the `toStructure()` method, we create a structure collection
                                        $items = $page->structure()->toStructure();
                                        // we can then loop through the entries and render the individual fields
                                        foreach ($items as $item) : ?>
                                            <div class="palette-box">
                                                <div class="image-container">
                                                    <h3><?= $item->label()->html() ?></h3>
                                                    <img src="<?= $item->image()->toFile()->url() ?>">
                                                </div>
                                            </div>
                                        <?php endforeach ?>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <a class="button-two" href="/kontakt"><?php echo $site->mehr(); ?> </a>
            </div>
        </div>
    </div>
</div>

<!-- ======= Snippets ======= -->

<?php snippet('info-block') ?>
<?php snippet('footer') ?>

And this is the Javascript code for the slideshow:

// jQuery Popup Slideshow Code for Produkt Übersicht Pages

$(document).ready(function () {
  // Initialize variables
  var images = $(".clickable-image");
  var currentIndex = 0;

  // Function to open the modal and display the image, name, beschreibung, and accordiontiteleins
  function openModal(
      index,
      name,
      beschreibung,
      accordionbeschreibungeins,
      accordionbeschreibungzwei
  ) {
      if (index >= 0 && index < images.length) {
          var imgUrl = $(images[index]).attr("src");
          $("#popup-image").attr("src", imgUrl);
          $("#popup-name").text(name);
          $("#popup-beschreibung").html(beschreibung); // Use .html() for rendering HTML
          // Update the accordion title here
          $("#popup-accordionbeschreibungeins").html(accordionbeschreibungeins); // Use .html() for rendering HTML
          $("#popup-accordionbeschreibungzwei").html(accordionbeschreibungzwei); // Use .html() for rendering HTML
          $("#myModal").css("display", "block");
          currentIndex = index;
      }
  }

  // Function to navigate to the next item
  function nextItem() {
      var nextIndex = currentIndex + 1;
      var nextTrigger = $(".popup-trigger").eq(nextIndex);
      if (nextTrigger.length > 0) {
          var name = nextTrigger.attr("data-name");
          var beschreibung = nextTrigger.attr("data-beschreibung");
          var accordionbeschreibungeins = nextTrigger.attr(
              "data-accordionbeschreibungeins"
          );
          var accordionbeschreibungzwei = nextTrigger.attr(
              "data-accordionbeschreibungzwei"
          );
          openModal(
              nextIndex,
              name,
              beschreibung,
              accordionbeschreibungeins,
              accordionbeschreibungzwei
          );
      }
  }

  // Function to navigate to the previous item
  function prevItem() {
      var prevIndex = currentIndex - 1;
      var prevTrigger = $(".popup-trigger").eq(prevIndex);
      if (prevTrigger.length > 0) {
          var name = prevTrigger.attr("data-name");
          var beschreibung = prevTrigger.attr("data-beschreibung");
          var accordionbeschreibungeins = prevTrigger.attr(
              "data-accordionbeschreibungeins"
          );
          var accordionbeschreibungzwei = prevTrigger.attr(
              "data-accordionbeschreibungzwei"
          );
          openModal(
              prevIndex,
              name,
              beschreibung,
              accordionbeschreibungeins,
              accordionbeschreibungzwei
          );
      }
  }

  // Add click event handlers to open the modal with name, beschreibung, and accordiontiteleins
  $(".popup-trigger").click(function (e) {
      e.preventDefault();
      var index = $(".popup-trigger").index(this);
      var name = $(this).attr("data-name");
      var beschreibung = $(this).attr("data-beschreibung");
      var accordionbeschreibungeins = $(this).attr(
          "data-accordionbeschreibungeins"
      );
      var accordionbeschreibungzwei = $(this).attr(
          "data-accordionbeschreibungzwei"
      );
      openModal(
          index,
          name,
          beschreibung,
          accordionbeschreibungeins,
          accordionbeschreibungzwei
      );
  });

  // Add click event handlers for next and previous buttons
  $("#nextSlide").click(nextItem);
  $("#prevSlide").click(prevItem);

  // Close the modal when the close button is clicked
  $(".closeButton").click(function () {
      $("#myModal").css("display", "none");
  });

  // Close the modal when clicking outside the modal content
  $(window).click(function (event) {
      if (event.target == $("#myModal")[0]) {
          $("#myModal").css("display", "none");
      }
  });

  // Click event handler for clickable images in the slider
  $(".clickable-image").click(function (e) {
      e.preventDefault();
      var index = $(".clickable-image").index(this);
      var name = $(this)
          .closest(".beds-box")
          .find(".popup-trigger")
          .attr("data-name");
      var beschreibung = $(this)
          .closest(".beds-box")
          .find(".popup-trigger")
          .attr("data-beschreibung");
      var accordionbeschreibungeins = $(this)
          .closest(".beds-box")
          .find(".popup-trigger")
          .attr("data-accordionbeschreibungeins");
      var accordionbeschreibungzwei = $(this)
          .closest(".beds-box")
          .find(".popup-trigger")
          .attr("data-accordionbeschreibungzwei");
      openModal(
          index,
          name,
          beschreibung,
          accordionbeschreibungeins,
          accordionbeschreibungzwei
      );
  });
});

I had to leverage JavaScript to output the values entered in the kirby panel. Plain php will not do it.
For example, normally, I’ll use <span ?php echo $page->accordionbeschreibungeins(); ?></span> to output the value for accordionbeschreibungeins, but since the value is not being outputted on the front end, I had to add code to the JavaScript code above, and the code snippet for outputting the value will look like this <span id="popup-accordionbeschreibungeins"></span> instead of this <span ?php echo $page->accordionbeschreibungeins(); ?></span>

Also notice how the values are being outputted for these:
<h4 id="popup-name"></h4> <p id="popup-beschreibung"></p>

While this method does output the value entered in the kirby panel, it may not be the right method. But I could be wrong. Grateful for your guidance.

I updated this text for better clarity:

I had to leverage JavaScript to output the values entered in the kirby panel. Plain php will not do it.
For example, normally, I’ll use <span ?php echo $page->accordionbeschreibungeins(); ?></span> to output the value for accordionbeschreibungeins, but since the value is not being outputted on the front end, I had to add code to the JavaScript code above, and the code snippet for outputting the value will look like this <span id="popup-accordionbeschreibungeins"></span> instead of this <span ?php echo $page->accordionbeschreibungeins(); ?></span>

Also notice how the values are being outputted for these:
<h4 id="popup-name"></h4> <p id="popup-beschreibung"></p>

While this method does output the value entered in the kirby panel, it may not be the right method. But I could be wrong. Grateful for your guidance.

You lost me a bit :confused:

In your previous message, you said this <span ?php echo $page->accordionbeschreibungeins(); ?></span> was not outputting in the front end.

This is not valid. It should be <span><?php echo $page->accordionbeschreibungeins(); ?></span>.
Maybe that helps?

Sorry, this <span id="popup-accordionbeschreibungeins"></span> will output the value entered in the kirby panel field. But this <span><?php echo $page->accordionbeschreibungeins(); ?></span> will not.

So, when I used the code <span><?php echo $page->accordionbeschreibungeins(); ?></span> you provided, the value is no longer being shown on the front end.