Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

Rendered Body Content for SinglePage Ajax Request

edited September 2012 in Framework

Hello,

this is my first post in this forum, so "hello" to all.

First of all: ElefantCms is awesome! Thanks to everybody who contributed to this!

Here is my Question: I'm trying to built a Single-Page Website with Backbone.js. So I built an app to retrieve all the Infos as a json. But i couuld not figure out how to get the page body completly rendered.

Here is the link to what i got at the moment, it has not really any content yet and requires a canvas capable Browser: http://beta.die-symbionten.de/

$page->layout = false;

if(empty($this->params)){
    $pagePath = $_GET["path"];
}else{
    $pagePath = implode("/", $this->params);
}


if (! User::require_admin ()) {
    $pages = Webpage::query ()
    ->where ('access', 'public')
    ->where ('id', $pagePath)
    ->fetch_orig ();
}else{
    $pages = Webpage::query ()
    ->where ('id', $pagePath)
    ->fetch_orig ();
}



if(!empty($pages)){
    foreach ($pages as $page) {
        $pageArray = $page;
    }

    unset ($pages);

    // i hoped this works, but unfortunatly it doesnt 
    $pageArray->body = $tpl->render ('../layouts/'. $pageArray->layout, $pageArray->body);          

    // thats how Im doing it atm, but its of course not a desirable solution
    // $pageArray->body = file_get_contents ('http://beta.die-symbionten.de/'.$pagePath);


    $n = new Navigation;
    $pageArray->path = $n->path ($page->id); 

    header ('Content-Type: application/json');
    echo json_encode ( $pageArray);
    $this->quit ();
} else {
    header ('Content-Type: application/json');
    echo "{'containsError':'true', 'Error': '$pagePath not found'}";
    $this->quit ();
} 

Comments

  • edited September 2012

    If you want to render the full page with layout for each page, then this should do it:

    if (! empty ($pages)) {
        $n = new Navigation;
    
        foreach ($pages as $k => $page) {
            $pages[$k]->body = $tpl->render ($page->layout, $page);
            $pages[$k]->path = $n->path ($page->id);
        }
    
        header ('Content-Type: application/json');
        echo json_encode ($pages);
    } else {
        header ('Content-Type: application/json');
        echo "{'containsError':'true', 'Error': '$pagePath not found'}";
    }
    

    You can take out the $this->quit() (just use return if you need) because $this->layout = false will stop it from adding a layout around your output, but still use gzip compression for the output. And in the above you only instantiate one Navigation object too.

    If you just want the page body, minus the layout, for each page to be rendered with any dynamic embeds it may have, you could replace the $tpl->render line with:

    $pages[$k]->body = $tpl->run_includes ($page->body);
    

    This method looks for any {! blog/headlines !} blocks in the body and replaces them with calls to those handlers. So the page body wouldn't contain the rest of the layout, which may be better for a single-page app, but it would have embedded content rendered as expected.

    I'd recommend taking a look at Elefant's RESTful API class too:

    This offers a nice way of organizing AJAX calls when building client-side apps. For my current project, I've built the entire site as a RESTful API and wrote a JavaScript wrapper library that everything runs through for it, basically like this:

    This tutorial may also be useful for you. It may need some updating, but the Elefant parts should still be current:

    Cheers!

  • Thanks a lot, i look into this :-)

  • Nice looking layout by the way @betaman.

  • He he, thanks for the flowers .-)

  • It worked, almost:-) Im doing it like this now:

    if(!empty($pages)){
        foreach ($pages as $page) {
            $pageArray = $page;
        }
    
        $n = new Navigation;
        $pageArray->path = $n->path ($pageArray->id);   
        $pageArray->body = $tpl->run_includes($pageArray->body);    
    
    
        header ('Content-Type: application/json');
        echo json_encode ( $pageArray);     
    } else {
        header ('Content-Type: application/json');
        echo "{'containsError':'true', 'Error': '$pagePath not found'}";        
    } 
    

    thanks for the super quick help!

  • Maybe I'm going to redo it later on and go with restful Api.

  • Looking at your code again, you can eliminate the foreach loop like this:

    $page->layout = false;
    
    if (empty ($this->params)) {
        $pagePath = $_GET["path"];
    } else {
        $pagePath = implode ("/", $this->params);
    }
    
    if (! User::require_admin ()) {
        $page = Webpage::query ()
        ->where ('access', 'public')
        ->where ('id', $pagePath)
        ->single ();
    } else {
        $page = Webpage::query ()
        ->where ('id', $pagePath)
        ->single ();
    }
    
    if ($page) {
        // convert it from a Webpage object into an ordinary object
        $page = $page->orig ();
    
        $n = new Navigation;
        $page->path = $n->path ($page->id);
        $page->body = $tpl->run_includes ($page->body);
    
        header ('Content-Type: application/json');
        echo json_encode ($page);     
    } else {
        header ('Content-Type: application/json');
        echo "{'containsError':'true', 'Error': '$pagePath not found'}";        
    }
    

    single() is handy for fetching just one result as an object instead of an array of one object. orig() returns the internal data object that the Webpage model manages, since single() returns a Webpage whereas fetch_orig() returned the internal data objects, so that's why that line is needed too :)

  • Thanks for the tweak and thumbs up for letting me know ;-)

  • it works, but don't call the queryResult "$page" (it throws a 500 Error probably because it overwrites real $page :-)

  • Ah yes, my bad :)

Sign In or Register to comment.