Jump to content
OLSA

Widgets and page field

Recommended Posts

Hello for all,

I try to find solution for my problem but without success.

I want to create selectable "widgets" option (banners) inside pages, and for that try to use Ryan "Blogprofile" principle:

1. create page widgets (hidden) with blank ("no file") template

2. inside page Widgets, child pages are different type of content (image+link, text box with some link, link lists etc...)

3. every "banner" has it's own template with markup

Inside Home page I created page field type (asmSelect) and set that selectable parent template is "widgets". 

And all that works, no any problems with administration - I can select desired widget/banner.

Because some desired eg. "Home" page doesn't know what kind of content is some widget (image+link, or text box with link, some list etc...) I use this in _main.php

// _main.php

$widgets = $page->widgets;
if(!$widgets || !count($widgets)) $widgets = $homepage->widgets;
foreach($widgets as $widget) {
  echo $widget->render(); // echo $widget shows correct ID
}

And some "banner" inside banner template has this (example):

// banner.php

$out = "<h4>{$page->title}</h4>";
echo $out;

But I have problem that page (website) not load?

Inside errors log ("site/assets/logs") I don't have any problem, everything is clean.

My opinion is that I don't use correctly render() method??? My template structure is like latest PW (2.5.3) multilanguage profile.

Thanks for any help.

Share this post


Link to post
Share on other sites

not totally sure, but i think you are trying to render a page without a .php template; how would the system know how to render the widget, maybe i'm not seeing your full picture..

Share this post


Link to post
Share on other sites

@Macrura thanks for answer,

but Yes I have template file for every widget type (eg. banner.php), and parrent page (Widgets) use template but without file (just like Widgets inside "Blogprofile").

Share this post


Link to post
Share on other sites

I get totally strange behavior with website loading, and at some moments I get this error inside error. log:

"Maximum function nesting level of '100' reached, aborting! (line 733 of ......wire\core\Page.php)"

I tried to change limit to 200, and also disable xdebug, but that didn't solve my problem.

I will try to find some different approach to get selectable widgets inside pages/templates (try to avoid render() method).

Thanks. 

Share this post


Link to post
Share on other sites

As Macrura pointed out,

1. create page widgets (hidden) with blank ("no file") template

seems to indicate that you have not linked the widget template with the banner.php file. When using $widget->render(), Processwire will check the template of the $widget Page object (I assume it's the widget template), and use its template file to render. If it doesn't have any (i.e. if you didn't set a template file), it will simply return an empty string. What you would need to do is manually set the template file to use for rendering like this:

// Assumes that "banner.php" is in the /site/templates folder
$widget->render($config->paths->templates . "banner.php");

But I think that the better way to do this is as follows:

  • Create a widgets-catalog template with no template file, but with access restrictions to prevent anyone from viewing directly this page and its children. Then create a "Widgets catalog" page. This will be the parent page for all your different widgets, whatever their type.
  • Create different templates for different widget types (e.g., text-banner, image-banner, etc.) which each have the relevant fields (file + link fields for the image-banner, text + link fields for the text-banner, etc.). Each of these templates has a corresponding template file in the /site/templates folder.
  • Create a widgets page field, with selectable pages set to having "Widgets catalog" as the parent page.
  • Add the widgets field to the home page and any other pages that you want.

Now you can select any widget type with the widgets field, and use $widget->render(), which will use the correct template to render.

Share this post


Link to post
Share on other sites
But I think that the better way to do this is as follows:
  • Create a widgets-catalog template with no template file, but with access restrictions to prevent anyone from viewing directly this page and its children. Then create a "Widgets catalog" page. This will be the parent page for all your different widgets, whatever their type.
  • Create different templates for different widget types (e.g., text-banner, image-banner, etc.) which each have the relevant fields (file + link fields for the image-banner, text + link fields for the text-banner, etc.). Each of these templates has a corresponding template file in the /site/templates folder.
  • Create a widgets page field, with selectable pages set to having "Widgets catalog" as the parent page.
  • Add the widgets field to the home page and any other pages that you want.

Now you can select any widget type with the widgets field, and use $widget->render(), which will use the correct template to render.

Yes, that is what I done, sorry if I was not clear enough in my first post.

Share this post


Link to post
Share on other sites

The maximum function nesting thing reeks of recursion. Maybe one of your widgets tries to render itself or some other page that also has this widget? Perhaps inside a prepended/appended file? Is _main.inc auto-appended?

  • Like 3

Share this post


Link to post
Share on other sites

The maximum function nesting thing reeks of recursion. Maybe one of your widgets tries to render itself or some other page that also has this widget? Perhaps inside a prepended/appended file? Is _main.inc auto-appended?

Yes and thanks for this, because that's help me.

What I want is that widgets (partials) need to be last in processing - and - widget can be any kind of content type (template).

Also, I know that all this can be done using some checks (function) and with known path to some partial (eg. $config->paths->templates . "banner.php" ) - but I want flexible principle inside main layout template file, and use at least possible logic for that job (later some new partials can be easily added to some new pages - without coding).

And @ Jan Romer, in my case _main.php is appended, and because I neglected that very important part - I get website loading problem. 

Finally I solve my problem when added 'appendFile'=>null to render() options.

// _main.php
// main layout template file
// appended

$widgets = $page->widgets;
if(!$widgets || !count($widgets)) $widgets = $homepage->widgets;
foreach($widgets as $widget) {
  echo $widget->render('', ['appendFile'=>null]); //'appendFile'=>null
}

With this I get desired result, very simple can add different content type widgets (partials, banners) to different pages.

Best regards and thanks!

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By MilenKo
      Hey everyone. I am at a stage of code cleaning for my first PW profile where I decided to implement some sidebar widget logic that would allow me to remove code repetition. I read about a few widget logic approaches that were working fine but that seemed too complicated for my needs so decided to implement something really simple that would do just that - widget logic that can be changed through the admin but not through code editing.
      So before I share my idea, I would give you some info of the structures I have:
      -- Recipes
      ---- Child 1
      ---- Child 2
      -- Ingredients
      ---- Child 1
      ---- Child 2
       
      So in my project needs, I wanted to have a solution that would allow me to set through the profile admin one or group of widgets per template (it would allow unlimited widgets as far as I have the code for it).
      So to achieve this functionality, I took the following steps:
      1. Create a template, called widget_logic and set the allowed template for children to be itself (widget_logic)
      2. Create a page Site Widgets and assign to it the widget_logic template.
      3. Create a field called listing_widgets and set its type to Page Reference.
      4. In Details tab select Multiple Page Array to allow multiple widgets to be selected.
      5. In the input tab chose Page Auto Complete as input field type.
      6. In Selectable pages point the parent to your widgets page name (Site Widgets in this example) and set the widgets_logic as the template.
      7. Repeat the steps 3-6 creating another field: inner_widgets (this would allow you to have different widgets per listing template and inner page )
      7. Add manually the child pages with the widgets names in Site Widgets page you just created.
      8. Assign the fields to the parent templates that you want the widgets to be pulled from (in this case: Recipes, Blog etc.)
      9. In the template code, pull the page parent through API using the loop you use to list the results in the page. For this tutorial I will set the widgets to Recipes template that shows a listing of all the recipes matching my criterias:
      //Build a selector and limit page results to 5 $result = $page->children("limit=5, sort=-published"); //Pull the parent of the first child-page to be used for widget logic $parent = $result->first()->parent(); 10. Once we know the parent and we know the field names assigned to it containing the widgets, we use a simple loop in each template to get the selected widgets name and include them where needed. Note, for the widgets naming I used: widget-XXX-YYY.php (eg. widget-recipe-top.php). If you prefer other naming, make sure you change the include line to match the new names.
      //Loop through all the widgets setup in the parent template foreach ($parent->listing_widgets as $w) {     //Including all the widgets by file name and order set in the parent widgets field     include ('./includes/widget-' . $w->title . '.php'); 11. In the Recipe-inner template I would do the same:
      $parent = $page->parent(); //Loop through all the widgets setup in the parent template foreach ($parent->inner_widgets as $w) {     //Including all the widgets by file name and order set in the parent widgets field     include ('./includes/widget-' . $w->title . '.php'); } NOTE: in the inner page template I changed the field name to inner_widgets to pull the widgets for the inner page.
      12. Now all that is left is to assign the two fields to every parent and/or inner page template that you would like to use the simple widget logic and select the widgets for each one.

      It might not be the best approach, however it is super simple to setup and allows me to have different widgets on any template now. The variety of widgets could be extended at any time by just adding the new widget, create the page with the name for it and assign it to the chosen template. Having the Page Auto Select field would allow you to drag and drop the widgets to reorder them so it suited my needs perfectly. Hope it would for you as well. Any code improvements are more than welcome (as usual
      P.S. On the image of widgets view, I set the size of both fields to be 50% so that they show up on the same line and save the space and scrolling.

    • By RyanJ
      Hello,
      I have a page field type (Multiple pages(PageArray)) with the input field type as AsmSelect. 
      The admin users can select one or more pages from a list in the admin area. Some of those pages have children and if a checkbox is selected and the parent page has been added to the list, then I want to add the child pages as well on page save.  So in admin.php I am trying to set those id's, but I can't get them to save. Hopefully the code clears up what I am trying to do. I appreciate any assistance. 
      $pages->addHookAfter('save', function($event) { $pages = $event->object; $page = $event->arguments(0); //check if on template if($page->template == 'item') { //is the checkbox checked to add children if ($page->add_children == 1) { //get the values in the page field type field foreach ($page->page_assignment as $child) { //if selected pages have childen if ($child->numChildren > 0) { //loop through those children foreach ($child->children as $grandchild) { //set values. //$page->set('page_assignment', array($grandchild->id)) $page->page_assignment = array($grandchild->id); //we got the id of the page we need to s $pages->error($grandchild->id); } } } } }  
    • By Tony Carnell
      Hi all,
      Real newbie question here; how do you get a child page's title from its parent's ID?
      Let me elucidate.
      I have a page type of Dam with 600+ dam child pages. Each child dam page uses a template called dam, and one field within the dam template is country, which is linked to a Countries page type.
      I've written code to return all the dams in a certain country, but it returns that country's ID as it appears in the dam template's country field.
      Having attempted and failed miserably to get the title of the appropriate country's child page's title from the ID, I thought I'd ask those far more knowledgeable than myself!
      I appreciate this is probably day one, lesson one of how to work with Processwire, but I'm still negotiating the learning curve 
      Tony.
    • By Tony Carnell
      Hi all,
      I'm a newbie to PW but can definitely see the power and potential that it holds, but I have a question that I'd like your guy's opinions on to help steer me down the best path.
      I am working on a project to make a searchable catalogue of a certain type of dam, each one having in excess of 20 criteria that describes them, including name, owner, country, dimensions, construction dates, construction methods and statistics.
      I've imported the dam database into PW and it's created a Page called 'dams' with 497 children for all the dams (forgive me if I'm not using the correct terminology, as I say I am a newbie!). It's also created fields for all the different criteria.
      What I'm wondering is if this is the best way forward?
      When I take a look at the backend of the Skyscraper Demo site (which has the same kind of functionality that I'm hoping to employ) I see that there's separate pages for Architects and Cities.
      Is there a benefit in storing the information like this?
      Does it make the search functionality on the front-end more powerful or easier to create?
      Would it be best to have a separate page for Dam Owners and Countries for instance, or is having them simply as fields within the dam page enough to allow me to work with them easily?
      Thanks in advance for any help or advice you have to offer, and if there's any more information you need to know, just ask.
      Tony.
    • By enricob
      Hi all,
      I am trying to create a page field type that let the user choose a field among the list of the all the fields (to clarify: the list of fields under Setup > Fields), but I cannot make it work.
      I tried this:
      I created the field, I set the type to "Page", I went to Input tab and changed the attribute "Parent of selectable page (s)" : here I select "Home > Admin > Setup > Fields".
      The problem is if I go to the page the new field is there but the dropdown is empty, there are not values in it.
      Why? Is it because core pages like templates or fields are hidden by default?
      Any help is appreciated. Thank you!
×
×
  • Create New...