Jump to content

function inside a widget inside another page issue [solved]


Joss
 Share

Recommended Posts

Okay, I am trying to do something slight silly. (again)

I have a file full to the brim with functions. For instance:

function getChildCategoriesPosts($page=null) {
    if(!$page) $page = wire('page');
loads of stuff
}
 
 
When I call that into a page it works fine, as you would expect.
 
Now, the tricky bit.
 
I want to add it to a widget (that is a page with template in its own right) and then add that widget to my main page using a page select field.
 
The trouble is, the function then uses the widget page as its source of inspiration rather than the main page that the widget is rendered into.

How can I get the right reference into the function so that when it asks for wire('page') it gets the information from the main page and not the widget page?

I am not 100% sure this is actually possible ... 

Joss

Link to comment
Share on other sites

Not sure. I will have to try

I think the problem is that the function is not actually called into the main page, it is called into the widget page. So when you ask for $page you get the widget.

Because this is used in lots of different main pages, I cannot give it a specific page, only the page it ends up being rendered in, if you see what I mean.

By the way, thanks for your help on the URL segments - I have now written that up on the Wiki.

Link to comment
Share on other sites

Not sure I understand. You said your widget is a page in a field of the main page? So "main" page would be $page and widget is $page->widgetfield ...? Now if you call that function 

getChildCategoriesPosts($page);

The function will use the main page as $page (remember $page doesn't exist yet in the function, you have to declare it and it can be something completely different than $page outside of the function. For clarity it might help to use a different name than $page)

If you call

getChildCategoriesPosts($page->widgetfield);

the widget page will be used .

I hope I'm understanding this correctly ...

Link to comment
Share on other sites

Okay, I am starting at this and getting lost in my own work flow. So let me try and write it out see if I can make sense of it.

Remember, that in this, all the functions actually are in a single included file, but that might not matter.

So...

1. I have a category page that I am going to view.

2. In the category page I call a function that retrieves pages (widgets) that are listed in a page field within a central setting page.

function categorySidebarWidgets() {
    $categoryWidgets = wire("pages")->get("/content-management/settings/site-settings")->site_category_sidebar_widgets;
    foreach ($categoryWidgets as $categoryWidget) {
        echo $categoryWidget->render();
    }
}

3. The page field select a widget that has its own template and template file (obviously)

 
It only has a title field.
 
4. In the widget template file I call a function
getChildCategories();
 
5. The function lists out the child pages (sub categories) of the category page I am viewing 
 
(That is the function I talked about earlier)
 
 
Currently I am doing it exactly as above.
 
If I ignore all that and just call the function into the category template, then it lists the category page, followed by the children.
 
However, If I do it as above, it lists the widget page, not the category page. It doesn't list any children since the widget page doesn't have any.
 
 
Does that make sense?
 
Sorry, this is a really mad route round! But it means that the widget position and location can be managed through the admin - so there is some good reasons behind the mess!
 
 
Joss
Link to comment
Share on other sites

Hi Joss,

are there more than one site_category_sidebar_widgets? I've never used the render() method so I have no idea how to access the main page. I usually use php includes which live in the scope of the main page ... What's in the template of site_category_sidebar_widget? Only that function?

Link to comment
Share on other sites

There can be many. The page field is a multiple select.

The templates of the various widgets vary and are mostly the normal markup of title, text and so on.

For this particular widget, however, the template has the title field but also the getChildCategories(); function call.

However, that function thinks it is talking about the widget.

There must be a way of declaring a global on the category page which can then be passed to the widget page and thus to the function. But I cant seem to break through the barrier between the category page and the widget page.

Obviously there has to be a barrier there otherwise when I call $page->title on the widget template file I would end up with the category title - and I don't or course.

Link to comment
Share on other sites

Here is a simpler scenario that may help - if I can get this to work then the original problem should fall into place.

I create a widget template that has the following code in it.

echo $page->sidebar 

The widget is called into another page (call it the mother page) using a page field. The output of the page field simply uses render().

The sidebar I want to display belongs to the mother page that the widget is called into.

At the moment, it displays the sidebar field belonging to the widget template (well, it would if the widget template had one!)

That is how it is meant to work, of course.

So, WHAT do I echo so that I get the sidebar field belong to the mother page that has the page field that calls in the widget?

(You know, however I write this, it always comes out as "there was an old lady who swallowed a fly...")

Joss

Link to comment
Share on other sites

Hi Joss,

you somehow need to pass that $page object of the mothership onto the widget page and into that function. I'm not on my coding computer right now and can't test anything but maybe you could simply attach it to the widget object

function categorySidebarWidgets() {
    $categoryWidgets = wire("pages")->get("/content-management/settings/site-settings")->site_category_sidebar_widgets;
    foreach ($categoryWidgets as $categoryWidget) {
        
#
$categoryWidget->mothership = wire('page');
#
        echo $categoryWidget->render();
    }
}

And then test if you can output $page->mothership->title in your widget template. If you can, run with it!

Oops, Interrobang war schneller

Link to comment
Share on other sites

Ok I think I know what you mean.

Current $page isn't available in your function when called from a page you render with $object->render() right? Since it's hard coded into function with wire("page") you could also pass it with an argument. My last 4 function examples showed this. Without reading the whole book here...

This has come up once or twice in the forums. Ryan showed an easy solution but can't remember exactly as there's some different cases and ways.

Ok here it goes.

From the you load the widget pages you di something like this to save the current page temporarely:

$item = $pages->get("/item/"); // some widget page
$item->calledfrom = $page; // save current page from where widget is rendered
echo $item->render();

Now in the template of the item you simply can use calledfrom and give it to the function 

echo "called from page: ". $page->calledfrom->title; // show the title of the page where this is rendered.
echo $page->title;
echo $page->body;
// call function with current page argument
myFunction($page->calledfrom);

Guys I'm getting slow... :P but three times holds longer.

  • Like 2
Link to comment
Share on other sites

HI Soma

Okay, that worked! 

I boiled it down to:

On the mother template:

$item = $pages->get("/content-management/widgets/sidebar/"); // some widget page
$item->calledfrom = $page; // save current page from where widget is rendered
on the widget template:
 
getChildCategories($page->calledfrom); 
The next question is:
 
Is there some generic way of passing this value from the mother page to the widget page without having to start by specifying a particular widget page?
 
I suspect there isn't, but I need to possibly render up to 6 different widgets like this that are doing different functions - it would be nice to have some way of covering any function in one hit - so one value that basically is the mother saying "this is me" that I can use in any widget that is rendered into that page.
Link to comment
Share on other sites

Not a problem, mate!

I will try and find the old posts from Ryan that you talked about

Thanks!

Edit: Okay solved it!

It is still a tiny bit limited, but perfectly useful.

So, on the mother page:

$items = $pages->get("/content-management/widgets/")->children; // some widget page
foreach($items as $item){
$item->calledfrom = $page; // save current page from where widget is rendered
} 

It was worth a shot just trying it.

Thanks again Soma.

Link to comment
Share on other sites

It's simple but you have to take care of it, and best is when you render them out, mostly in a foreach loop. This is perfectly fine and requires only 1 line at the end.

Nerd alert...

What I meant was going further and do it literally add a new template var that is always the current page viewed.

In a autoload module, take HelloWorld.module as example you do the init() like this.

public function init() {
    // no need to hook in admin area, we only need it on frontend
    if(strpos( "/" . $this->input->get("it"), $this->config->urls->admin) !== FALSE) return;
    // hook view process when ready to get current page
    $this->addHookAfter('ProcessPageView::ready', $this, 'getMother');
}
/**
* get current page and create a new template variable
*/
public function getMother($event) {
    $page = $this->getFuel('page');
    $this->setFuel("motherpage", $page);
}
 

Now anywhere in your template code you could use 

$motherpage

or 

wire("motherpage") 

Nerd alert end.

(cool now the forum editor has proper code indentation but instead we get lots of extra lines and mess-ups more than before and takes more works posting code blocks :/ ...)

Link to comment
Share on other sites

Yep - definitely over-nerded there!

The trouble is, I am not totally sure why the first version works, let alone the long version!

I ought to find out at some point and write it up - it is one of those useful techniques that should be not just buried in the forum.

As for the code blocks - yes, they can be very ...... roomy!

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...