Jump to content

Something like Gutenberg/Drupal Paragraphs?


artfulrobot
 Share

Recommended Posts

I have found the 'repeater' field type which lets me repeat a set of values to a single set of fields on a page. What I'm after is something that lets me add sets of *different* fields.

eg. define one thing as 'hero', which has an image and a big title. define another thing as "text with image on left" (formatted text and image fields ). define another thing as "three reasons" (a set of three text, icon, title, link fields)

Now on one page I want to add: hero, text with image on left, three reasons, text with image on left.

On another page I want to add: text with image on left, 3 times.

Can I achieve this with processwire?

Link to comment
Share on other sites

Out of the box (without third party modules) your best option is the Page Table ("ProFields: Page Table") fieldtype. It's included with the core package, but might be uninstalled by default.

The user interface for Page Table is a bit different in that you'll edit content in modal windows instead of "in context", but I'd suggest that you give it a try. You can save your content items under current page, or a different location in your page tree.

If third party modules are an option, the Repeater Matrix module is worth checking out. It's commercial (paid) module, but if that's not an issue, it's really quite amazing. Other (non-commercial) module options include PageTableNext and PageTableExtended.

  • Like 1
Link to comment
Share on other sites

On 8/27/2022 at 2:31 PM, teppo said:

Out of the box (without third party modules) your best option is the Page Table ("ProFields: Page Table") fieldtype. It's included with the core package, but might be uninstalled by default.

The user interface for Page Table is a bit different in that you'll edit content in modal windows instead of "in context", but I'd suggest that you give it a try. You can save your content items under current page, or a different location in your page tree.

If third party modules are an option, the Repeater Matrix module is worth checking out. It's commercial (paid) module, but if that's not an issue, it's really quite amazing. Other (non-commercial) module options include PageTableNext and PageTableExtended.

I know "ProFields Table", the "ProFields Page Table" I have not found after downloading the ProFields. Where can I find ProFields Page Table? How do I add these "Page Table" field?

Link to comment
Share on other sites

@kaz on my install "ProFields: Page Table" is listed in the core things I can install. I did not have to download anything extra. Perhaps you have an older version of PW?

I am experimenting with that module but needing to step back to understand the rendering process; at the mo I get whole 'pages' output, with header navs etc. for each item in my Page Table field! I'm still evaluating, but I'm not sure I like/want the individual 'paragraphs' (Drupal speak) or 'blocks' (Gutenberg speak) to be separate pages with separate publication statuses, URLs etc., but I may get to something usable in the end. It's new for me to deal with the concept of non open source documentation for a (now) open source project; seems quite strange. Anyway, I'm still experimenting, I thought I should try to understand that module first before the PageTableNext one etc.

Open source is a must for me, so I'm not going to evaluate Repeater Matrix.

  • Like 1
Link to comment
Share on other sites

3 hours ago, kaz said:

I know "ProFields Table", the "ProFields Page Table" I have not found after downloading the ProFields. Where can I find ProFields Page Table? How do I add these "Page Table" field?

Page Table was developed/intended as a part of the ProFields bundle, but later bundled with the core package, so "ProFields" in the name is kind of a nod towards that history ?

2 hours ago, artfulrobot said:

I am experimenting with that module but needing to step back to understand the rendering process; at the mo I get whole 'pages' output, with header navs etc. for each item in my Page Table field!

There are many ways to handle rendering, but here's one solution that may help you:

  • Create a shared root for your content elements — something like /blocks/ or /content-elements/, perhaps.
  • Configure your Page Table field to save new items below aforementioned root path, and make sure that you only enable templates that you've created for this purpose. You don't want to allow a "regular basic-page" (or anything like that) in your Page Table field as a "content element".
  • For each of your "content element templates", leave template file empty (so that these pages can't be reached with their actual URL).

Now even though your content elements will be actual pages in the page tree, they won't be reachable by visitors. You can render them in any way you see fit, but here's one approach using ProcessWire's native field rendering feature that, in my opinion, works pretty well. Here I've assumed that the Page Table field is called "blocks", and it's used on template called "basic-page".

/site/templates/basic-page.php

<?php namespace ProcessWire; ?>

<?= $page->render('blocks') ?>

/site/templates/fields/blocks.php

<?php namespace ProcessWire; ?>
<?php foreach ($value as $item): ?>
    <div class="block">
        <?= $item->render(__DIR__ . '/blocks/' . $item->template . '.php') ?>
    </div>
<?php endforeach; ?>

/site/templates/fields/blocks/block_template_name.php

<?php namespace ProcessWire; ?>
<h2>
    <?= $page->title ?>
</h2>
<?= $page->content ?>

Anyway, as I mentioned that's just one approach ?

2 hours ago, artfulrobot said:

It's new for me to deal with the concept of non open source documentation for a (now) open source project; seems quite strange.

I'm not entirely sure what you're referring to here, but if you mean the processwire.com website, then yes — that's technically proprietary. In my experience that's a common thing for open source projects. API reference, on the other hand, is automatically generated from ProcessWire's source code, so that is technically open source ?

  • Like 6
Link to comment
Share on other sites

Wow, didn't expect such an awesome detailed reply, thanks! Can't wait to try it out.

Re non floss docs, I may have misunderstood, but I felt like the docs for page table were not public based on things on other forum threads and also on the page that explains about the paid core 'pro' modules and how they may one day be released free but the support (which i thought might include docs) would be just for those who paid. I've probably misunderstood, so sorry if so!

 

 

Link to comment
Share on other sites

I have a field called 'sections', and $page->render('sections'); in basic-page.

I have a templates/fields/sections.php file which is very much like your /site/templates/fields/blocks.php. It assumes templates at templates/fields/sections/{template_name}.php.

I have a template called 'hero' which is set up and has content and a template file at templates/fields/sections/hero.php

However, loading the page alternately gives Bad Gateway and a massive stack dump error:

( ! ) Warning: include_once(./_func.php): failed to open stream: No such file or directory in /var/www/processwire/site/templates/_init.php on line 34

I think this might be because _init is being loaded twice, once for the actual page page being loaded, and then again when called from the PageTable field template,s/fields/sections.php file which calls render() on a Page object in the loop.

I found the answer in the docblock comment to the _init.php file/template:

Quote

If you want to disable this automatic inclusion for any given template, go in your admin to Setup > Templates > [some-template] and click on the "Files" tab. Check the box to "Disable automatic prepend file".      

Disabling the prepend (_init) and append (main) files fixed it.

So thank you, I'm getting somewhere!

One thing I don't understand though is that my IDE says that the signature for Page->render() is:

 * @method string|mixed render($fieldName = '') Returns rendered page markup. If given a $fieldName argument, it behaves same as the renderField() method. #pw-group-output-rendering

But here I'm providing a template file path?

 

 

Link to comment
Share on other sites

I've found a nice solution using PageTableNext.

- I can define different section(block/paragraph...) types with appropriate fields, e.g. hero, text with image on right, ... I can create templates for all these.

- I can add/delete/reorder/edit etc. these to a page and see previews in-editor.

 

Thanks for the help.

  • Like 1
Link to comment
Share on other sites

Quote

  I've found a nice solution using PageTableNext.
- I can define different section(block/paragraph...) types with appropriate fields, e.g. hero, text with image on right, ... I can create templates for all these.
- I can add/delete/reorder/edit etc. these to a page and see previews in-editor.

Hi at artfulrobot,

That sounds very interesting, Besides from Teppo, do you have some code examples ?

Link to comment
Share on other sites

@pwired sure, here you are.

 

site/templates/fields/sections_next.php

This file is responsible for outputting rendered HTML for the field called `sections_next`. It's called with the `$value` set to the value to be rendered, which in this case is a field of type PageTableNext.

<?php
namespace ProcessWire;
/**
 * @global Page $page
 * @global PageArray $value
 * @global Field $field
 * @global Pages $pages
 * @global Config $config
 */

?>
<div style="margin:1rem;border:solid 1px yellow; background:#ffffe0;padding: 1rem;">
  This is sections_next.php
<?php if(!($value instanceof PageArray)) return;

foreach($value as $contentElement)
echo '<div style="border:solid 1px #fc0;background:#eefff8;padding:1rem;margin:1rem;">
  The following is rendered by '
  . $contentElement->template->name . '<br />'
  . $page->renderValue($contentElement, ($field->pathToTemplates ?? '')
  . $contentElement->template->name)
  . '</div>';
?>
</div>

 

site/templates/fields/sections/hero.php

This file and the one that follow are two example possible section/paragraph/block types. For my proof of concept, I created a "hero" one and a generic "section" one. This hero one crudely renders a big background image with some big text over the top.

<?php namespace ProcessWire;

$image = $value->background_image;
$thumb = $image->size(1920, 700);
?>
<div style="background-image:url(<?php echo $thumb->url ?>);
  padding: 4rem;margin: 0 0 2rem 0;min-height:60vh;">
  <p style="color:#fc0; font-size:3rem; font-weight:bold;
    text-align: center; line-height: 1.4;">
    <?php print $value->title; ?>
  </p>
</div>

site/templates/fields/sections/section.php

The 'section' type has a body field and a select field letting the user choose Blue/Mauve/None for the background colour.

<?php namespace ProcessWire;

// here, $page is the main page tht was requested; $value is the Page object being rendered, the 'section'.
?>
<?php
$map = ['Blue' => '#0284ea', 'Mauve' => '#f0ddff', 'None' => 'transparent'];
$selected = $value->background_colour->title;
$bg = $map[$selected ?? 'None'];
?>
<div style="border:solid 1px #cf0;background:<?php echo $bg; ?>;
    padding:1rem;margin:1rem;">This is section.php, rendering <code>$value</code>
  <h2>title: <?php print $value->title ?></h2>
  <p>colour: <?php print $value->background_colour->title ?></p>
  body: <?php print $value->body ?>
</div>

Other files

Now the instructions for PageTableNext (ptn) tell you to copy some other files into your templates dir, but I've not figured out why! e.g. The instructions made me copy a file from the module to site/templates/PageTableNext/ptn.php, however I put exit() at the top of that file to test whether it was ever used and I've not found it to be doing anything, so I don't understand that!

Here's my demo page content:

image.thumb.jpeg.f19491735f58c210c32268a56500d633.jpeg

In the editor it looks like this:

image.jpeg.abc60a08e33eadd8b355a1e27d9988e8.jpeg

➊ shows the three blocks/sections/... that I've added (with the buttons at ➌). I clicked the arrow to 'open' the third section and you can see it at ➋ rendered using just the site/templates/fields/sections/section.php file.

The UI is pretty nice; you can edit each section, move them around etc.

Oh, one other thing, in the main page template (e.g. basic-page.php) you need to render the field that contains all the blocks/sections/etc.  like so:

<?php
// If using 'delayed' output:
$content = $page->render->sections_next;

// If using 'direct' output
echo $page->render->sections_next;

One interesting thing is that if you use delayed output then your site/template/{page-type-name}.php needs to populate $content (or whatever vars you use in _main.php). However, the field templates all just use echo/print because they are rendered with output buffering capture.

Hope this helps! It might help me too when I come to actually make a site with PW instead of just playing!

 

 

  • Like 9
Link to comment
Share on other sites

  • 1 year later...
On 8/31/2022 at 6:48 PM, teppo said:

There are many ways to handle rendering, but here's one solution that may help you:

  • Create a shared root for your content elements — something like /blocks/ or /content-elements/, perhaps.
  • Configure your Page Table field to save new items below aforementioned root path, and make sure that you only enable templates that you've created for this purpose. You don't want to allow a "regular basic-page" (or anything like that) in your Page Table field as a "content element".
  • For each of your "content element templates", leave template file empty (so that these pages can't be reached with their actual URL).

Now even though your content elements will be actual pages in the page tree, they won't be reachable by visitors. You can render them in any way you see fit, but here's one approach using ProcessWire's native field rendering feature that, in my opinion, works pretty well. Here I've assumed that the Page Table field is called "blocks", and it's used on template called "basic-page".

I have done it this way, but I think the link is missing.
I have a page table field section_blocks. As described, I did not select an >Details >Template.

In the /fields folder I have a section_blocks.php

<?= $item->render(__DIR__ . '/section-blocks/' . $item->template . '.php') ?>

I render it in my basic template:

<?= $page->render('section_blocks') ?>

For this I have two two simple templates:
/site/templates/fields/section-blocks/block_content.php
/site/templates/fields/section-blocks/block_gallery.php

When I open the page in the editor, I get the following error message:

Please select a template before using this field.
Please specify one or more columns in the settings before using this field.

What I can't find in the configuration of the section_blocks field:

Configure your Page Table field to save new items below aforementioned root path, and make sure that you only enable templates that you've created for this purpose.

So the connection is missing, and I wonder, how do I set up the connection? What have I overlooked?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...