Using a builder snippet from a different page

I’ve got this snippet defined in snippets/blocks/cta.php:

<div class="container">
  <a class="btn" href="<?= $data->content()->url() ?>">Join us!</a>
</div>

Is there any way to re-use this snippet from a different page? I know that I can pass data via the snippet function (e.g. snippet('blocks/cta', array('data' => $page)), but in this case I’d have to add a url field to the $page object I’m passing along? Is there any better way?

Start over: Ok, you are using content here because of the conflict with the url() method, right?

And you want to use the snippet with content from the current page, but use $page->url() of course, and not the content of a url() field. Wondering if you have to use content() here at all, since $data is not a page object.

Awesome, this works:

<?php snippet("blocks/cta", ["data" => $page]) ?>

or even

<?php snippet("blocks/cta", ["data" => page("join-us")]) ?>

and the snippet:

<div class="container">
  <a class="btn" href="<?= $data->url() ?>">Join us!</a>
</div>

Now, if I want to be able to change the link text as well, is there a way to pass it along as well, even if $page or page(“join-us”) don’t have that field?

Yes, you can make it dynamic, but then you have to pass the variable every time you call the snippet:

Snippet:

<a class="btn" href="<?= $data->url() ?>"><?= $linktext ?></a>

In template:

<?php snippet("blocks/cta", ["data" => $page, 'linktext' => 'Join us']) ?>

or when using it in the builder loop:

<?php snippet("blocks/cta", ["data" => $block, 'linktext' => $block->linktext()]) ?>

Right. But that won’t work if I use a specific field from my builder blocks, e.g. $data->headline(). Is there a way to add this field to $page and just passing the data array/page object?

Why not? That’s why I posted the second example above.

But of course you can also add a field to your pages. You can even use a different fieldname, if you make the fieldname dynamic and pass it to the snippet.

Because I can’t add additional variables to my builder loop. No other block makes use of these variables:

foreach($page->builder()->toBuilderBlocks() as $block) {
    snippet('blocks/' . $block->_key(), array('data' => $block));
}
<?php snippet("blocks/cta", ["data" => page("join-us")]) ?>

works however and I was wondering if I could add fields to the data object/array?

Yes, you can, by adding a condition:

foreach($page->builder()->toBuilderBlocks() as $block) {
    $data = ['data' => $block];
    if ($block_key() === 'name_of_block_with_linkfield') {
        $data['linktext'] = $block->linktext()->value();
    }
    snippet('blocks/' . $block->_key(), $data);
}

Or shorter:

foreach($page->builder()->toBuilderBlocks() as $block) {
    snippet('blocks/' . $block->_key(), [
       'data' => $block,
       'linktext' => $block->linktext()->exists() ? $block->linktext()->value() : null
    ]);
}

It is irrelevant if the $linktext variable is used in the snippet or not.

Oh right, now I get it. Thanks for the explanation!

I was just wondering if there is a way to do the same thing without modifying the builder loop. Like modifying the data object before using the snippet as usual. Something like (not working):

$data = page("join-us");
$data['linktext'] = "Join us";
snippet("blocks/cta", ["data" => $data]);

Not like that, but like this:

// add filters
$data = ['data' => page("join-us")];
$data['linktext'] = "Join us";
snippet("blocks/cta", ["data" => $data]);

Yeah, that was what I thought as well, but it gives me this error:

Call to a member function url() on array

site/templates/session.php:

[...]
<?php
$data = ['data' => page("join-us")];
$data['linktext'] = "Join us";
snippet("blocks/cta", ["data" => $data]);
?>
[...]

site/snippets/blocks/cta.php:

<a class="btn" href="<?= $data->url() ?>"><?= $data->linktext()->escape() ?></a>

Oh, yes, right, because it you then would have to use $data['data'].

You can modify it like this:

snippet("blocks/cta", [
    "data" => page("join-us"),
    'linktext' => 'join us'
]);
1 Like