cjx2240

Best approach to a long page/unique template with many different fields

Recommended Posts

Just wondering what everyone's approach is to a long page which requires many different pieces of input.

For example, imagine your homepage is laid out like this:

  • Banner
    • Title
    • Subtitle
    • Multiple background images
    • Links
  • Second banner
    • Title for area
    • Paragraph of text
    • Background image
    • Bullet points
  • Third text area
    • Image
    • Links
    • List of feature with a title/description for each
  • Call to action/banner
    • Image
    • Text
    • Link
  • News section introduction
    • News section title
  • Final call to action
    • Title
    • Description
    • Link/link text
  • List of partner logos
    • Description
    • List of images/links

And most of these fields are not used on other parts of the site. Now, I can start of using a nice repeater matrix for banner images. I can use title, and then I can make a text field. I can make a text_2 and a text_3 and maybe a text_4 and I'm going to be able to reuse those in other templates too. I can make image, image_2 and the same thing applies. When it comes to a list of features, I might go with a ProFields Table. I have read Making efficient use of fields in ProcessWire - I found I was already using the advice within (a good read nonetheless) but still don't feel like my delivery is that efficient.

Because a long list of fields like this is going to get incredibly busy and confusing. And is calling a lot of repeaters and a lot of different fields for this template alone going to slow the site down? Also there's a holdup every time you realise you need a new field and you have to go and create it, then save the template so you can select it. 

Is there a better way? I think I dream of some kind of unlimited "text" field that you can create as many of as you need to... (Not like ProFields Table, where the user can create as many as they want, but where the admin can make them on the fly while setting up the template)

We could hardcode some of these small titles etc but in my opinion that will just quickly lead to the user asking "where do I change this line of text?" I could use a wysiwyg for areas of titles and descriptions but in my experience this quickly leads to broken layouts.

I know this is very general but I wonder if people have a smart approach to this kind of template setup that I have not considered.

Share this post


Link to post
Share on other sites

I have used that quite a lot, and it's suitable to this page in some ways, however, it allows the user to make as many of these sections as they want and re-order them, which leads to needing much more development on the front end to account for the items being in any order or missing altogether.

Maybe a solution would be something like Limit Table (which I found indispensable for alleviating my original issue) - but for Repeater Matrix....

Share this post


Link to post
Share on other sites
23 minutes ago, cjx2240 said:

Maybe a solution would be something like Limit Table (which I found indispensable for alleviating my original issue) - but for Repeater Matrix....

Limit Table works by hiding elements within the inputfield in Page Edit. You can make a custom solution for Repeater Matrix (or any inputfield) by using your browser tools to find the class/ID of the elements you want to remove, and hiding them with a display:none CSS rule. Add the custom styles selectively to Page Edit via a hook:

$wire->addHookAfter('ProcessPageEdit::execute', function(HookEvent $event) {
    $page = $event->object->getPage();
    $out = $event->return;
    // match to the relevant page(s) however suits you
    if($page->template->name == 'my-template') {
        $out .= "
        <style>
        /* Put your custom CSS here */
        </style>
        ";
        $event->return = $out;
    }
});

 

  • Like 3

Share this post


Link to post
Share on other sites

@cjx2240

here's my 2cents:

- for those configurable pages, i use a pagetable, in combination with the Micro Contexts module... this allows me to have 1 template for all of those items but to hide/show fields and change their order, descriptions, labels, notes and even conditional hide/show based on the 'type' of widget (e.g. section). this is working really well for me because on 'turn-key' site, you never know how many custom sections you will need to build, and it would be a drag to have to keep creating new templates; in this system you just need to add each section as an option (e.g. page reference for the section type) and then load the corresponding file using some code like this:

if(count($page->sections_pt)) {
    $sections = '';
    foreach($page->sections_pt as $section) {
        if(file_exists('./partials/sections/section-' . $section->widget_type->name . '.php')) {
            $viewBag['widget'] = $section;
            $sections .= "\n" . wireRenderFile('./partials/sections/section-' . $section->widget_type->name, $viewBag);
        }
    }
    $content = $sections;
}

 

  • Like 2

Share this post


Link to post
Share on other sites

@Macrura sorry but I think the way that Micro Contexts works is going over my head a little. Maybe a video would be good to explain how that works? I'm not suggesting that for my sake but just to get the idea across for other users!

PageTable looks good but just like Table and RepeaterMatrix my problem is that you can make as many as you want, reorder them, delete them etc.. I just need something that is like a parent field, containing other fields. Perhaps using @Robin S's suggestion and hiding all the controls on a repeater matrix might be the answer....

Share this post


Link to post
Share on other sites
On 14/06/2017 at 9:21 AM, Robin S said:

Limit Table works by hiding elements within the inputfield in Page Edit. You can make a custom solution for Repeater Matrix (or any inputfield) by using your browser tools to find the class/ID of the elements you want to remove, and hiding them with a display:none CSS rule. Add the custom styles selectively to Page Edit via a hook:

I tried this and it worked great! Thanks. I put it in admin.php. I targeted RepeaterMatrixes where the name ended in _fixed, as that appears as a class around the item.

For anyone else who wants to use this, it's worth noting that it's important to have some if statement, if you just load it on every page you will get js errors when the file is called by ajax (eg image upload)

I still think there's a place though for a simple field that contains fields, without allowing you to make as many as you want. It could also have the option to be put into tabs the way fieldgroup start/end currently works.

Share this post


Link to post
Share on other sites
14 hours ago, cjx2240 said:

if you just load it on every page you will get js errors when the file is called by ajax (eg image upload)

True. To avoid this add...

if($this->config->ajax) return;

...at the top of the function. Alternatively you can add a linked stylesheet to the <head> instead of adding the styles directly to the Page Edit source. Something like:

$wire->addHookAfter('ProcessPageEdit::execute', function(HookEvent $event) {
    $page = $event->object->getPage();
    // match to the relevant page(s) however suits you
    if($page->template->name == 'my-template') {
        $this->config->styles->add($this->config->urls->templates . 'admin-custom/my-styles.css');
    }
});

This is a good way to go if you package the function and stylesheet together into a simple module.

  • Like 2

Share this post


Link to post
Share on other sites
On 6/14/2017 at 9:31 AM, cjx2240 said:

@Macrura sorry but I think the way that Micro Contexts works is going over my head a little. Maybe a video would be good to explain how that works? I'm not suggesting that for my sake but just to get the idea across for other users!

ok sure - i will try and make this short and as relevant to this topic as possible, but ultimately this does relate to the age old discussion of how to implement configurable pages that has many topics and long discussions on the forum, so this problem/solution is somewhat based on researching and trying every option and arriving at this as the currently best option for creating turnkey websites:

The problem: You want to implement a user interface that allows site editors to create and update page sections; in some cases these page sections may be orderable and in other cases you might want to restrict the ability of the editors to change the order. You may also want the user to be able to change from one type of section to another similar type of section with ease and not having to have some complex instructions for how to do that. One example might be a callout - perhaps there are 3-4 different types of callouts, one is a full width, and another is a split box. Another option might be a hero section where options include static image, video, or slider.

The user should be able to switch the type of section type without having to create a whole new section and copy their content and prefs to the new section. They should not be required to go to the settings tab and change the template and have to go through that process.

Based on these requirements, any interface that asks the user to specify the section type (template) prior to adding the new section will not work - this means no repeaters, and no page tables that use multiple templates. 

The solution i use is to let users add a new section to the page table, and on the section template, they can select the type of section to use (a field). The 'section type' field is a page reference (single select), which pulls the options from a hidden branch of the page tree. The sections for any page are output by checking for the existence of a corresponding php file (where the selected option's page name corresponds to the file name of the php file) in a directory in the templates folder. Each section's php file renders the section, and is a completely self contained file that includes all of the necessary code to render the section. I use a theme engine that also allows any section to inject dependencies into the header or footer, and set/modify other theme options/variables.

Based on your outlined fields, you have mostly common field requirements between your sections:
Title [title]
Subtitle [subtitle]
Multiple background images [images]
Links [links table or repeater]
Title for area [title]
Paragraph of text [body]
Background image [images - use first one]
Bullet points [body]
Image [images - use first one]
Links [links table or repeater]
List of feature with a title/description for each [features repeater]
Image [images - use first one]
Text [body]
Link [links table or repeater - use first one]
News section title [title]
Title [title]
Description [body]
Link/link text [links table or repeater - use first one]
Description [body]
List of images/links [possibly repeater, or images extra with url field?]

The micro contexts system would simply allow you to change the field labels, descriptions, notes, order, visibility and required based on the page reference selection for the section type...

  • Like 2

Share this post


Link to post
Share on other sites

@Macrura, your Micro Contexts idea is clever. The approach you are taking here (effectively a single template where fields may be shown/hidden and labels/descriptions changed depending on context) is in fact exactly what is done in Repeater Matrix. Every matrix item (page) actually has the same fields, but the field visibility and labels etc are controlled by the matrix type context.

So that got me thinking that all that is needed to do something similar with Repeater Matrix is to add some control that allows the user to change the matrix type of an existing Repeater Matrix item. The advantages over the Micro Contexts approach are:

  • You don't have multiple templates that must be kept in sync if new fields are added - if you add a new field to any given matrix type it is added to the single Repeater Matrix field template.
  • You can do all your field overrides (visibility, width, label, description, notes) from a single screen (the Repeater Matrix field settings).
  • So as a result it's quicker to set up and easier to maintain.

I have put in a request to Ryan to add such a control, but I had a play around and managed to get something working with a couple of hooks. To use this...

  1. Create a new text field named 'block_type' (best to create a dedicated field for the purpose). Set the field visibility to 'Closed' (to keep it discreet).
  2. In your Repeater Matrix field settings, add the block_type field as the first field in each matrix type.
  3. Add the hooks below to /site/ready.php...
// Change the block_type inputfield to a matrix type select
$wire->addHookAfter('InputfieldText::render', function(HookEvent $event) {
    $inputfield = $event->object;
    $field = $inputfield->hasField;
    if(!$field || $field->name !== 'block_type') return;
    if($inputfield->name === 'block_type') return; // in case field is not being rendered inside repeater inputfield
    $rpage_id = str_replace('block_type_repeater', '', $inputfield->name);
    $rpage = $this->pages->get($rpage_id);
    if(!$rpage->id) return; // just in case
    $matrix_field_name = substr($rpage->template->name, 9);
    $matrix_field = $this->fields->get($matrix_field_name);
    $raw_matrix_types = $matrix_field->type->getMatrixTypes($matrix_field);
    $matrix_types = [];
    foreach($raw_matrix_types as $key => $value) {
        $label = $matrix_field->get("matrix{$value}_label");
        $matrix_types[$value] = $label ?: $key;
    }
    $if = $this->modules->get('InputfieldSelect');
    $if->name = $inputfield->name;
    $if->label = $inputfield->label;
    $if->required = true;
    foreach($matrix_types as $key => $value) {
        $if->addOption($key, $value);
    }
    $if->value = $rpage->repeater_matrix_type;
    $event->return = $if->render();
});

// Change the matrix type on saveReady
$pages->addHookAfter('saveReady', function(HookEvent $event) {
    $page = $event->arguments(0);
    if(!$page instanceof RepeaterMatrixPage || $page->block_type === null) return;
    if($page->isChanged('block_type')) $page->setMatrixType($page->block_type);
});

If you wanted to remove certain Repeater Matrix inputfield controls then you would use a hook/module as discussed in earlier posts in this thread.

matrix.gif.c7f71d634496ab02791f7cc38f07d6a3.gif

  • Like 5

Share this post


Link to post
Share on other sites
10 hours ago, Robin S said:

The approach you are taking here (effectively a single template where fields may be shown/hidden and labels/descriptions changed depending on context) is in fact exactly what is done in Repeater Matrix. Every matrix item (page) actually has the same fields, but the field visibility and labels etc are controlled by the matrix type context.

Wow didn't know that; i had avoided repeater matrix in this particular scenario because the pages i use for the sections have a lot of fields, and use a 2-column layout as well; Also, i like to be able to direct edit the sections from the page tree once in a while; but certainly for simpler applications, the repeater matrix sounds awesome and i'll have to give it a go soon...

Another reason why the Micro Contexts idea will still be useful is for templates that are not in a repeatable context; But you have brought up the issue of the interface, so perhaps i need to have a process module that can show the various related contexts on 1 screen...

Share this post


Link to post
Share on other sites
On 14.6.2017 at 10:21 AM, Robin S said:

Limit Table works by hiding elements within the inputfield in Page Edit. You can make a custom solution for Repeater Matrix (or any inputfield) by using your browser tools to find the class/ID of the elements you want to remove, and hiding them with a display:none CSS rule. Add the custom styles selectively to Page Edit via a hook:


$wire->addHookAfter('ProcessPageEdit::execute', function(HookEvent $event) {
    $page = $event->object->getPage();
    $out = $event->return;
    // match to the relevant page(s) however suits you
    if($page->template->name == 'my-template') {
        $out .= "
        <style>
        /* Put your custom CSS here */
        </style>
        ";
        $event->return = $out;
    }
});

 

Didn't read the whole thread but just wanted to let you know that you don't need the hook here. The body has a class with the template name, so a single css selector would be enough ;) Don't know when this feature was implemented though.

EDIT: this is a feature of AOS, not core...

body.ProcessPageEdit-template-YOURTEMPLATE ...

 

  • Like 1

Share this post


Link to post
Share on other sites
On 14/06/2017 at 7:52 PM, cjx2240 said:

Maybe a solution would be something like Limit Table (which I found indispensable for alleviating my original issue) - but for Repeater Matrix....

@cjx2240, I made a new module...

 

  • Like 1

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.