Add anchor to "read more" button

For the dramatic effect of a jump from the intro of a blog post to…
.
.
.
exactly the word inside the text of the blogpost, I created a custom block that basically just renders an empty span with an ID, which value I can type into the block field and then insert that block anywhere in a blogpost.

This thing works. It renders this:

<span id="ziel"></span>

Now I struggle to make the “read more” button have that ID attached to its url.

My button ist the standard button/ link, which is used in a snippet for an intro for the blog page. Like this:

<a href="<?= $article->url() ?>" class="article-more">mehr... ></a>

I tried to attach something like $article->anker()->toBlocks() to that button, like this:

<a href="<?= $article->url() ?>#<?= $article->anker()->toBlocks() ?>" class="article-more">mehr... ></a>

But that gives me nothing.

I tried several variations of this incl. ->uid() although I didn’t expect it to be the right guess, which it isn’t. I cannot insert the content of the “anker”-block into the button. I also guess that I will need an if statement around that link in case I don’t insert one of my “anker”-blocks, but thinking about it (again) as I type this, I think I don’t need one.

PS:

That “anker”-block (its not a full blown block, like for adults, it is maybe more of a “blocklet” ;)) is built like this:

plugins/anker/blueprints/blocks/anker.yml

name: anker
icon: url
fields:
  anker:
    type: slug
    help: Hier eine Bezeichnung der ID als Stichwort eingeben und Anker am Ziel einfügen.

plugins/anker/snippets/blocks/anker.php

<span id="<?= $block->anker()?>"></span> 

plugins/anker/index.js

panel.plugin("leblog/anker", {
    blocks: {
        anker: `
          <input
            type="anker"
            placeholder=" Ziel des Ankers…?"
            :value="content.anker"
            @input="update({ anker: $event.target.value })"
          />

        `
    }
});

plugins/anker/index.php

<?php

Kirby::plugin('leblog/anker', [
  'blueprints' => [
    'blocks/anker' => __DIR__ . '/blueprints/blocks/anker.yml'
  ],
  'snippets' => [
    'blocks/anker' => __DIR__ . '/snippets/blocks/anker.php'
  ]
]);

Well, this cannot possibly work because your anker is inside a blocks field. So let’s find the block first:

$ankerBlock = $article->blockFieldName()->filterBy('type', 'anker')->first();

Then we can check if this block exists, to get the value of its anker field:

$slug = $ankerBlock ? $ankerBlock->anker()->html() : '';
<a href="<?= $article->url() ?>#<?= $slug ?>" class="article-more">mehr... ></a>

I guess I get the php statement wrong. I did <?php ?> . I tried <?= ?> and an if statement but thats all wrong.

The anker block is in a group of fieldsets, does that play a role? No, does it or maybe?

This is what I did:

    <!-- So let’s find the block first: -->

    <?php $ankerBlock = $article->anker()->filterBy('type', 'anker')->first(); 
     $slug = $ankerBlock ? $ankerBlock->anker()->html() : ''; ?>

   <!--  Then we can check if this block exists, to get the value of its anker field: -->

    <a href="<?= $article->url() ?>#<?= $slug ?>" class="article-more">mehr... ></a>

the blueprint with the sieldsets:

          post:
            type: blocks
            help: *Füge Blöcke für ein Cover-Foto o.Ä. hinzu und gestalte Deinen Beitrag mit Text und Bildern etc.*
            fieldsets:
              text:
                label: Text
                type: group
                fieldsets:
                  - anker
                  - text
                  - smalltext
                  heading:
                    extends: blocks/heading
                    fields:
                      level:
                        default: "h3"
                        options:
                          - h2
                          - h3
                          - h4
                      customId:
                          label: Custom ID
                          type: text
                  - list
                  - quote
                  - line
    
              media:
                label: Media
                type: group
                fieldsets:
                  image:
                    extends: blocks/image
                    fields:
                      stil:
                        label: Bildgestaltung
                        type: multiselect
                        options:
                          tiny: tiny
                          small: small
                          medium: medium
                          big: big
                          center: center
                          rounded: rounded
                          right: right
                          left: left
                          portrait: portrait
                          shadow-s: shadow-s
                          shadow-m: shadow-m
                          shadow-l: shadow-l
    
                  - video
                  - gallery
              code:
                label: Code
                type: group
                fieldsets:
                  - code
                  - markdown

But your field is called post, not anker, but I forgot to add the toBlocks() method:

<?php $ankerBlock = $article->post()->toBlocks()->filterBy('type', 'anker')->first();

Haha, I had tried post()->anker()but it produced such a big mess, that I quickly undid it, it looked much too wrong to try it further.

You said that the problem ist, that the anker thing is in a block. But why is it that the other blocks on the page work? Why do you have to find and define the anker-block first? Why do you have to get its content (the slug) out of that field? And why do I have to make into html?

Well, maybe I got it wrong, I thought you wanted to get the anker block content in your template with this link that did not work… :woman_shrugging:

<a href="<?= $article->url() ?>#<?= $article->anker()->toBlocks() ?>" class="article-more">mehr... ></a>

And it does it perfectly! I was just wondering why. Thank you!!