Issue configuring patterns with `preview` value

Hello,

I’ve started using the patterns plugin, and initial impressions are THIS IS GREAT!!

However, I’m running into issues for those patterns that require a specific ($page) context. For example, I have the following pagination component:

<nav class="c-pagination">
  <p class="c-pagination__count">
    <strong><?= $pagination->items() ?></strong> results.
    <? if($pagination->hasNextPage()): ?>
      Showing <strong><?= $pagination->numStart() ?></strong> - <strong><?= $pagination->numEnd() ?></strong>
    <? endif ?>
  </p>

  <p class="c-pagination__pages">
    <? if($pagination->hasPrevPage()): ?>
      <a rel="prev" href="<?= $pagination->prevPageURL() ?>">Previous</a>
    <? endif ?>

    <? if($pagination->hasNextPage()): ?>
      <a rel="next" href="<?= $pagination->nextPageURL() ?>">Next</a>
    <? endif ?>
  </p>
</nav>

Of course, outside the context of search results, this template makes little sense. I need to have this pattern render in a context where a value for $pagination is given. Ah, this is what the preview configuration value is for I thought, so I provided the following:

<?php

return [
  'preview' => function() {
    site()->visit('search?q=brighton');
  }
];

However, this has no effect. My impression was that this value simulates visiting a particular page, and then provides a pattern with the values needed. Is this not the case?

Additionally, for other patterns, I get a different error. So, for this configuration:

<?php

return [
  'preview' => function() {
    site()->visit('companies/south-eastern');

    return [
      'stations' => $pages->children()->filterBy('company', '*=', 'companies/south-eastern'),
      'context' => 'company'
    ]
  }
];

I get the following error:

Parse error: syntax error, unexpected '}', expecting ';' in /Users/paulrobertlloyd/Sites/bradshawsguide/site/patterns/section/stations/stations.config.php on line 11

Fatal error: Exception thrown without a stack frame in Unknown on line 0

Fatal error: Uncaught Whoops\Exception\ErrorException: Exception thrown without a stack frame in Unknown:0 Stack trace: #0 /Users/paulrobertlloyd/Sites/bradshawsguide/site/plugins/patterns/vendor/filp/whoops/src/Whoops/Run.php(356): Whoops\Run->handleError(16, 'Exception throw...', 'Unknown', 0) #1 [internal function]: Whoops\Run->handleShutdown() #2 {main} thrown in Unknown on line 0

What am I doing wrong? Am I configuring my patterns properly?

site()->visit() does not set params, so you need to set it manually. The following should do the trick:

$_GET['q'] = 'brighton';
site()->visit('search');

That’s just a syntax error. There is a semicolon missing in line 10 after the closing square bracket.

Wow, thanks for the super-quick response. Much appreciated :slight_smile:

Ah, right. I’ve filled a PR on the documentation so hopefully it doesn’t trip anyone else up!

Even with these fixes in place, I’m still getting errors that relate to contextual variables not being found. So, for my pagination component, I see:

There's an error in your pattern:
Undefined variable: pagination

while for my stations component, I get:

There's an error in your pattern:
Undefined variable: pages

This is the code for my stations pattern:

<?
  switch ($context) {
    case 'company':
      $title = "Stations served";
      break;
    case 'region':
      $title = "Stations in the county";
      break;
  }
?>
<section class="c-section c-section--stations">
  <h1 class="c-section__title"><?= $title ?></h1>
  <?
    pattern('section/index', array(
      'search' => $stations
    ));
  ?>
</section>

I’m including it my pages thus:

$companyPath = kirby()->request()->path(2);
pattern('section/stations', array(
  'stations' => $pages->children()->filterBy('company', '*=', $companyPath),
  'context' => 'company'
));

Is using preview config the best way to get these variables, or should I use another method? I note that a recommendation is to send the $page variable with each pattern, i.e.:

pattern('site', ['p' => $page ]);

That seems a little long-winded!

You can set the default for the pattern in the configuration like this:

return [
  'defaults' => [
    'title' => 'Default title',
    'text'  => 'Default text'
  ]
];

The default will be used when the pattern is called in your templates/snippets, unless overwritten by the pattern method.

You need to make sure that there is a default value for each variable by using the defaults option in the pattern configuration.

I’m using defaults for those patterns where it makes sense (i.e. passing a page title), but what about when more complex data is required (i.e. a collection of $pages)? For example, my pagination component needs a collection of pages as context for the $pagination variable. What would I set as the default for $pagination?

I think you should be able to do something like this:

$articles = page('blog')->children()->visible()->paginate(5);

return [
  'defaults' => [
    'articles'   => $articles,
    'pagination' => $articles->pagination()
  ]
];

Okay, I think I’m slowly (!) getting there. Ironed out a few of the issues I’m having, and getting a better sense of how this works.

But, put more simply, what is the best way of saying to a previewed pattern “you’re on this page”. Currently, $page seems to default to home, but in certain cases, I want to have the context of another page. I’m trying all manner of things in my config file, but none seem to work as expected, beyond using the pattern('patternName', ['p' => $page ]); method.

You can pass the page you need in the default, using the page helper:

return [
  'defaults' => [
    'p'   => page('somepage'),
  ]
];

Hope, that’s what you’re after.

Follow up solution for anyone who has the same issue. For my pagination component, I’m now using the following config:

<?php

$results = site()->search('brighton', 'title|text');
$results = $results->paginate(10);

return [
  'defaults' => [
    'pagination' => $results->pagination()
  ]
];

In my site, I call my pattern like so:

pattern('common/pagination', array(
  'pagination' => $results->pagination()
));

(Sidenote: I use a controller for my search page, which provides the value of $results.)

1 Like

The issue is (I’m guessing) that you can’t override the value of $page when previewing a pattern? For example, the following config doesn’t work:

return [
  'defaults' => [
    'page' => page('stations/brighton'),
  ]
];

So, if I want $page to varry, I need to create another variable, such as $p?

Yes, and that makes sense, as it might interfere with the use of $page in a template.

I am not sure if i am a little bit late, but i ran into the same issue.
I’ve got a template pattern wich is supposed to preview a whole page-type.
These pages must have access to the page variables set in the content folder.

So i’ve got my config-file:

<?php
return [
  'title' => 'Contact Page',
  'defaults' => [],
  'preview' => function() {
    return [
      'p' => page('contact')
    ];
  }
];

And i also added a little bit of logic at the very top of my template files:

<?php
if(isset($p)) {
	$page = $p;
}
?>

I was looking for a solution to manage this globally, but i was not able to find a good one.
As far as I know it is not possible via the site.php or via a controller. Correct me if i’m wrong.

Cheers,
Sven