How to add classes from checkbox to an extended layout block?

Day 2 on learning Kirby. I am pretty amazed but still don’t get some concepts after reading the documentation and watching videos.

I wonder how to add classes to a specific field element using checkboxes?

Here is my actual blueprint:

title: Layout

fields:
  layout:
    type: layout
    layouts:
      - "1/1"
    fieldsets:
      heading:
        extends: blocks/heading
        fields:
          class:
            label: Classes
            type: checkboxes
            options:
              heading-lg: Big Heading
              heading-sm: Small Heading

and my layout.php

<?php foreach ($page->layout()->toLayouts() as $layout) : ?>
    <section id="<?= $layout->id() ?>">
        <?php foreach ($layout->columns() as $column) : ?>
            <div class="column">
                <div class="blocks">
                    <?= $column->blocks() ?>
                </div>
            </div>
        <?php endforeach ?>
    </section>
<?php endforeach ?>

And my backend looks like this:

How do I bring that classes to my heading? I wonder how show my template look like.

Thanks a lot!

Since you have added the field to the heading block, you would make a copy of the default heading block snippet (in /site/snippets/blocks/heading.php), get the original code from heading | Kirby CMS, and make your changes as required.

In this example

<<?= $level = $block->level()->or('h2') ?> class="<?= $block->class() ?>"><?= $block->text() ?></<?= $level ?>>
1 Like

Thanks again @texnine. From the heart (:

So I imagine that would be the complete code:

<?php foreach ($page->layout()->toLayouts() as $layout) : ?>
    <section id="<?= $layout->id() ?>">
        <?php foreach ($layout->columns() as $column) : ?>
            <div class="column">
                <div class="blocks">

                    <?php foreach ($column->blocks() as $block) : ?>
                        <<?= $level = $block->level()->or('h2') ?> class="<?= $block->class() ?>"><?= $block->text() ?></<?= $level ?>>
        
                    <?php endforeach ?>

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

Is there a shorter way to have the same result?

Also I am getting a comma “,” when i select more than one class on the backend, outputting like this:

<h1 class="heading-lg, heading-sm"Test</h1>

Is there a way to get rid of that comma in the class?

No, no, no… With that code you would just render headings and nothing else.

As I said, you create a heading.php block snippet (put it in the path I gave you above) with the changes (see link and code above), then just render the blocks as in your original code block:

<?php foreach ($page->layout()->toLayouts() as $layout) : ?>
    <section id="<?= $layout->id() ?>">
        <?php foreach ($layout->columns() as $column) : ?>
            <div class="column">
                <div class="blocks">
                    <?= $column->blocks() ?>
                </div>
            </div>
        <?php endforeach ?>
    </section>
<?php endforeach ?>

Oh, and you shouldn’t use a checkboxes field but a select or radio or toggles field, you only want to apply one class for the heading size, not multiple (that’s why you get the comma).

Thank you @texnine. Actually what I posted is just one example to simplify, I have actually waaaaaay more simultaneous classes to add (or not) and I thought that checkboxes were a good choice. Maybe a multiselect.

Also I will use other fields, like text and image, markdown etc, but I was using the heading for learning purposes. I basically chose one field to try to add classes by user choice, technique that I am planning to use in other fields and layouts in general. So I imagined there is no other way than to foreach the blocks (and maybe for each the classes with split() to avoid the comma), but I am unsure it is the simpler and more elegant way.

So what is the way to go to add classes with checkboxes? Or other way?

I am really decided to learn Kirby :smiley:

Thanks a lot for the quick answers, it has been pretty helpful.

Is it the way to go? It works, but I still not sure if I could do it more simpler. If not, I let this as a solution for other people.

<?php foreach ($page->layout()->toLayouts() as $layout) : ?>
    <section id="<?= $layout->id() ?>">
        <?php foreach ($layout->columns() as $column) : ?>
            <div class="column">
                <div class="blocks">
                    <?php foreach ($column->blocks() as $block) : ?>
                        <?php
                        $level = $block->level()->or('h2');
                        $classes = implode(" ", $block->class()->split());
                        ?>
                        <<?= $level ?> class="<?= $classes ?>">
                            <?= $block->text() ?>
                        </<?= $level ?>>
                    <?php endforeach ?>
                </div>
            </div>
        <?php endforeach ?>
    </section>
<?php endforeach ?>

This code doesn’t make sense, because you will render this code for any block in the loop, no matter the type!

If you want to loop through all blocks individually, call their snippet by type. But do create the custom snippet.

But yes, for the classes, that’s the way to go!

All right, I will try with snippets. Thanks (:::

How do I pass a snippet to use in the backend as a field in the Layout Blueprint? I confess I am pretty lost.

After this, how to add my custom classes?

I must confess I’m also a bit lost, because I don’t understand your question. What is the backend in this case?

All right, I will try to reformulate the question.

My plan is to create a kind of Page Builder. In that page in the Panel (that’s what I called backend) I wish the users to add Layout sections. These sections should provide a flexible way for users to add as many fields as they want, such as headlines, paragraphs, and images, in any order they choose.

I am planning to benefit from the drag and drop feature from the Layouts in the panel.

I each field I would like to allow the users to choose a few design options, as I am creating a flexible template. That’s why the checkboxes, or radio, or multiselect fields. (I still deciding what fits best)


I got close to create it, but I got confused when it comes to create snippets for that purpose, as you recommended, like a headline snippet with flexible classes, or a text snippet with flexible classes.

What are my questions?

1 - How should I specify the snippet in the Layout blueprint in a way I can see it and edit it in the panel? What means “call snippet by type”?

2 - How can I add or remove the classes for those snippet in the panel?

3 - How can I finally output it all in the frontend?

I have been looking the documentation and videos, but could not find a solution for this.

I think we should get a few terms right:

When we talk about “snippets”, we refer to the PHP code that is used to render block types in the frontend. In those snippets, you have access to all fields that you add to your modified block.

The other part is displaying those field in the Panel. There you have two options:

  1. You create a custom block preview, many examples for this here: Block factory: Creating your own blocks collection | Kirby CMS

  2. You also show the fields instead of a proper preview, in Kirby 4 this will just be a setting in your blueprint, in current Kirby 3, you can use a plugin: Block Preview Fields | Kirby CMS

You do not edit the snippet via the Panel. In the snippet you render what is stored in the blocks fields.

By adding fields for whatever classes you needs. I’m not really sure what you want to add here. for example, if you wanted to specify classes for color, you would add a color field which several options etc. Somehow your example classes field in the heading block doesn’t seems useful, because those two options are mutually exclusive.

There we are back to what I said above: block snippets are responsible for the rendering the stuff in the frontend.

Maybe re-read the intro to the blocks/layouts field, in particular this section about the parts that make a block type: Page builder | Kirby CMS

:grimacing:

Oh oh, maybe I need some more time to assimilate the concepts and make lots of mistakes. I still kind of lost, even if i got the last days to read the documentation. But i imagine it is normal as there are not much complete examples with complex blueprint + template together.


In fact I understood Snippet as the Kirby feature of reusable blocks of code.

So in my question, a code example would be better understood. is my trouble in fact here?

<?= $block->text() ?>

Do you mind provide me with a corrected code?

<?php foreach ($page->layout()->toLayouts() as $layout) : ?>
    <section id="<?= $layout->id() ?>">
        <?php foreach ($layout->columns() as $column) : ?>
            <div class="column">
                <div class="blocks">
                    <?php foreach ($column->blocks() as $block) : ?>
                        <?php
                        $level = $block->level()->or('h2');
                        $classes = implode(" ", $block->class()->split());
                        ?>
                        <<?= $level ?> class="<?= $classes ?>">
                            <?= $block->text() ?>
                        </<?= $level ?>>
                    <?php endforeach ?>
                </div>
            </div>
        <?php endforeach ?>
    </section>
<?php endforeach ?>

I have been travelling far away reading all the documentation to understand it, that was good. That drove me to learn a bit more about snippets and snippets slots, but i have the sensation I went too far away for that case. I just don’t know how far. :joy:


In fact the heading classes are not super useful, they are just examples. They could be color classes as you mentioned, or anything else. In the future I will be defining classes properly, CSS is my mother language. (:

But thanks a lot for the support, I could not have a better start on a tool. Just question of time to the ideas get in place.

I’m referring to this example: Blocks | Kirby CMS

Each block type has its own snippet. The default snippets you can find here: https://github.com/getkirby/kirby/tree/main/config/blocks (each block type in this folder has a blueprint and a snippet) or in the documentation here for each block type.

I’m repeating myself, but this does not make sense, because this will loop through all blocks in that column and render it with code that is supposed to be for a heading block type, but not for the other block types that might exist within your layout column.

Therefore for this heading block code, you would create a heading snippet.

Yes, that’s true, but the same is true for blocks. The code that renders each block type lives in a snippet because it can be called a thousand times, i.e. as many times as you use a given block type in your pages. With the only difference that block snippets are located in /site/snippets/blocks and not in the snippets folder directly.

Screenshot 2023-07-19 at 21.02.06
(This is where you put your custom block snippets, the ones to overwrite the default block types as well as the ones for your custom block types)

So take what is in between the foreach loop and kindly put it in a heading block snippet. Then just call

<?php foreach ($column->blocks() as $block) : ?>
  <?= $block ?>               
<?php endforeach ?>

Now I got it!

It finally works, Endlich!

Thanks @texnixe for your patience!