• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Demo App without "nested Views" or "mass view loading" in the controller and unobtrusive Ajax (jQuery) (Tutorial)

#1
[eluser]Polarity[/eluser]
I see many threads in here about the same problem. You cant render different sections of a page. you have to call each view after another or have to include views into views. so i thougt i make a small helper, that renders a template and fill the regions. this example works, and you can copy it to your ci and test it for yourself.

Download | Demo Site

The main Problem with including Views in Views is, if you load a View, you get always the included Views too. So thats nice if you want to render the complete Page but not so comfortable if you want only the view without the included views (ajax calls). Plus if you want to pass some variables to the view in the view, you have to write many code and arrays that you have to copy to each controller / page and forward to every view. i think thats not elegant in the CIs way.

So you came maybe to the conclusion to call every View after another in the Controller. (header,content, sidebar, footer). That Produces also much Code, because you have to do it in every controller for every page. Plus you have to take care of your html structure in the views. Every view must be complete the other in the correct order. And you didtn see the whole site structure at once, only parts of it.

So i decided to make a Helper function for that. That Helper renders one View that have "regions" that you can fill with text/html. you can pass a array to that helper, so you have control over the regions. And he decides to render the full page or just give a region back for ajax manipulation.

The Code
I created one view that i called "views/layout.php" that view contains the complete site layout. header, content, sidebar footer etc. every section (sidebar/content) have a variable like that:

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
&lt;html &gt;

&lt;head&gt;
    &lt;title&gt;&lt;?=$site_title?&gt; | &lt;?=$site_name?&gt;&lt;/title&gt;
    &lt;meta http-equiv="Content-type" content="text/html; charset=utf-8" /&gt;
    &lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js">&lt;/script>
    &lt;base href="&lt;?=base_url()?&gt;" /&gt;
    &lt;style type="text/css" media="screen"&gt;
        #ss_contentwrapper {
            width:100%;
        }
        #ss_sidebar {
            width:20%;
            float:left;
            border:1px solid gray;
        }
        #ss_content {
            width:78%;
            float:right;
            margin:0px 0px 5px 5px;
            border:1px solid gray;
        }
        #ss_footer {
            border: 1px solid gray;
        }
        .ssArticle {
            margin: 5px;
            border:1px solid red;
        }
        .break {
            clear: both;
        }
    &lt;/style&gt;
    &lt;script type="text/javascript" charset="utf-8">
        $(document).ready(function() {
            $('a[rel=ajaxcall]').each(function(i){

                    // get the url from the a tag
                    var url = new Array();
                    var target = new Array();
                    url[i] = $(this).attr('href');
                    target[i] = $(this).attr('name');
                    
                    // remove the href attribute
                    $(this).removeAttr('href');

                    // do on click
                    $(this).click(function(){
                        // fade out the current Content
                        $(target[i]).fadeOut('slow',function(){
                            // load the content from the url
                            $(target[i]).load(url[i],function(){
                                // fade the new content in
                                $(target[i]).fadeIn('slow');
                            });
                        });
                    })
                });
        });
        
    &lt;/script>
&lt;/head&gt;

&lt;body id="ss_body"&gt;
    <div id="ss_wrapper">
        <div id="ss_header">
            &lt;?=$menu?&gt;
        </div>

        <div id="ss_contentwrapper">
            <div id="ss_sidebar">
                &lt;?=$sidebar?&gt;
            </div>

            <div id="ss_content">
                &lt;?=$content?&gt;
            </div>
            
            <div class="break"></div>
        </div>

        <div id="ss_footer">
            <p>Footer</p>
        </div>
    </div>
    
&lt;/body&gt;
&lt;/html&gt;

then we need a view for these regions. first the content loop for showing us the articles (for a blog maybe) "views/article.php"

Code:
<h1>&lt;?=$site_title?&gt;</h1>

&lt;?if(is_array($articles)):?&gt;
    &lt;?foreach($articles as $article):?&gt;
        <div class="ssArticle">
            <h1>&lt;?=$article['subject']?&gt;</h1>
            <p>&lt;?=$article['content']?&gt;</p>
        </div>
    &lt;?endforeach;?&gt;

&lt;?else:?&gt;
    <div>
        <p>Sorry no Articles there :(</p>
    </div>
&lt;?endif;?&gt;

and we need a view for the sidebar: "views/new_articles"
Code:
<h2>Recent Articles</h2>
&lt;?if(is_array($articles)):?&gt;
    <ul>
    &lt;?foreach($articles as $article):?&gt;
        <li>&lt;?=$article['subject']?&gt;</li>
    &lt;?endforeach;?&gt;
    </ul>
&lt;?else:?&gt;
    <ul>
        <li>No Articles</li>
    </ul>
&lt;?endif;?&gt;

#2
[eluser]Polarity[/eluser]
and a view for the menu "views/menu.php" put the "rel" attribute to add a ajax function and the "name" attribute with the css selector for the target div.
Code:
&lt;!--
    Links need a rel="ajaxcall" and a name="#myTargetCssId"
    
    rel="ajaxcall" means: if the user have javascript, just use ajax
    if not, just reload the complete site.
    
    name="#myTargetCssId" specifies: in wicht div should the content
    of the controller load. put in here a CSS id/class or jQuery selector
--&gt;
<ul>
    <li>&lt;?=anchor('mypage/index','Home',array('rel'=>'ajaxcall','name'=>'#ss_content'))?&gt;</li>
    <li>&lt;?=anchor('mypage/contact','Contact',array('rel'=>'ajaxcall','name'=>'#ss_content'))?&gt;</li>
    <li>&lt;?=anchor('mypage/articles','Articles',array('rel'=>'ajaxcall','name'=>'#ss_content'))?&gt;</li>
    <li>&lt;?=anchor('mypage/articles','Articles in the Sidebar',array('rel'=>'ajaxcall','name'=>'#ss_sidebar'))?&gt;</li>
</ul>

The Helper Function
then i created the helper function. that function do nothing more, than render the layout view and fill it with code at the regions. I added a ajax function to consider if the call is ajax or standard. "helper/template_helper.php" put this helper in the autoload to have it global.

Code:
&lt;?php
/**
* Renders the view with defaults or given data
*
* @param array $array index of your region with data to fill
* @param string $content Optional. if ajax call, wich content should be given back? arrayIndex
* @return void
* @author Robert Agthe
*/
function layout($array,$content = 'content')
{
    // get Instance from CI
    $CI =& get_instance();
    
    // we want some default content (new articles) on the sidebar
    // if the index "sidebar" on the array is empty
    // you can delete that construct, or modifiy it to
    // your needs. its just an example. maybe you dont want a
    // complex content fill like that
    if(!isset($array['sidebar']))
    {
        // Load the model or delete and -> autoload
        $CI->load->model('Article_model');

        // Get some new articles
        $data['articles'] = $CI->Article_model->getNew();

        // define the view region
        $layout['sidebar'] = $CI->load->view('new_articles',$data,true);
    }
    else // or if the index "sidebar" is filled
    {
        $layout['sidebar'] = $array['sidebar'];
    }

    // Check and Fill the Menu Region
    $layout['menu'] = (!isset($array['menu']))?$CI->load->view('menu',NULL,true):$array['content'];

    // Check and Fill the Content Region
    $layout['content'] = (!isset($array['content']))?'Nothing Set':$array['content'];

    // Check and Fill the Site Title
    $layout['site_title'] = (!isset($array['site_title']))?'Nothing Set':$array['site_title'];

    // Check and Fill the Site Name
    $layout['site_name'] = (!isset($array['site_name']))?'Nothing Set':$array['site_name'];

    // Ajax Call?
    if(is_ajax())
    {
        // just output the specified Region
        echo $layout[$content];
    }
    else
    {
        // Render the View
        $CI->load->view('layout',$layout);
    }

}

/**
* Checks if the call ajax or browser
*
* @return bool
* @author Robert Agthe
*/
function is_ajax()
{
    return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')?true:false;
}

#3
[eluser]Polarity[/eluser]
The Controller
so in the controllers i have nothing more to create an array an pass it to my helper function "layout()"

Code:
&lt;?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* My Homepage
* some Demo/Example Controllers
*
* @package default
* @author Robert Agthe
**/
class Mypage extends Controller {
    
    function Mypage()
    {
        parent::Controller();

        // Load the Template Helper here or in the Autoload.php
        $this->load->helper('template_helper');
        
        // Load the Model for the Articles
        $this->load->model('Article_model');
    }

    /**
     * Home - My first page
     * this shows you, that you can define all layout regions inside the controller
     * leave a array index empty and define in your helper function a default
     * content if you want on every page the same content for that region
     *
     * @return void
     * @author Robert Agthe
     **/
    function Index()
    {
        // Retrieve Data from the Models
        $data['content']['articles'] = $this->Article_model->getAll();
        $data['content']['site_title'] = 'Welcome';
        $data['sidebar']['articles'] = $this->Article_model->getNew();

        // Define Data for all Views
        $data = array(
            'site_name' => 'My Homepage',
            'site_title' => $data['content']['site_title'],
            'sidebar'=>'Here HTML, TEXT or pass another view with TRUE on the third param',
            'content'=>$this->load->view('articles',$data['content'],TRUE)
        );

        // Render the page with the Helper function
        layout($data);
    }
    
    /**
     * Contact - My second page
     * on this site we leave the default content and
     * and just fill the content area
     *
     * @return void
     * @author Robert Agthe
     **/
    function contact()
    {
        // Define Data for all Views
        $data = array(
            'site_title'=>'Contact',
            'content'=>'<h1>Contact</h1><p>You are on the contact site. thx</p>'
        );

        // Render the page with the Helper function
        layout($data);
    }

    /**
     * Ajax - An example
     * here you can just output a view without the
     * layout, to update a region with jQuery or Motools
     *
     * @return void
     * @author Robert Agthe
     **/
    function Articles()
    {
        // Retrieve Data from the Models
        $data['content']['articles'] = $this->Article_model->getNew();
        $data['content']['site_title'] = 'Another Headline';

        // Define Data for all Views
        $data = array(
            'content'=>$this->load->view('articles',$data['content'],TRUE)
        );

        // Render the page with the Helper function
        layout($data);
    }

}

at the end we need a model, to get the data from database etc. "models/article_model.php"
Code:
&lt;?
class Article_model extends Model {

    function Article_model()
    {
        parent::Model();
    }
    
    /**
     * Get all Articles
     *
     * @return array
     * @author Robert Agthe
     */
    function getAll()
    {
        // Dummy Data Array, just put your DB Query here
        return array(
            array('id' =>1,'subject'=>'My Model My Model','content'=>'text text'),
            array('id' =>2,'subject'=>'Another Article','content'=>'text text'),
            array('id' =>3,'subject'=>'Stupid Data lol','content'=>'text text')
        );
    }
    
    /**
     * Get recent articles
     *
     * @return array
     * @author Robert Agthe
     */
    function getNew()
    {
        // Dummy Data Array, just put your DB Query here
        return array(
            array('id' =>1,'subject'=>'Very New Article','content'=>'text text'),
            array('id' =>2,'subject'=>'Obama Wins','content'=>'text text'),
            array('id' =>3,'subject'=>'Air on the Moon','content'=>'text text'),
            array('id' =>4,'subject'=>'All eyes on me','content'=>'text text')
        );
    }
}

#4
[eluser]AndrewMalachel[/eluser]
Very interesting...

Can you give us a link to where we can see the script?
I'm curious about the Ajax function...
and also the [removed]...
Did you use ajax/javascript frameworks (like prototype or others) for ajax?

Can't wait to check it out... :-)

#5
[eluser]xwero[/eluser]
Polarity it is sufficient to add an html entity to 'fool' the forum filters.

If i get it, it's Friday so my mind is a bit fried after a weeks work, you load pageparts only using AJAX which means no javascript no pageparts, yes?

#6
[eluser]Polarity[/eluser]
[quote author="AndrewMalachel" date="1229721297"]Very interesting...
Can you give us a link to where we can see the script?[/quote]
yea i post a zip and maybe a demo later on or tomorrow

[quote author="AndrewMalachel" date="1229721297"]
I'm curious about the Ajax function...
and also the [removed]...
Did you use ajax/javascript frameworks (like prototype or others) for ajax?[/quote]
jQuery Smile

[quote author="xwero" date="1229722024"]If i get it, it’s Friday so my mind is a bit fried after a weeks work, you load pageparts only using AJAX which means no javascript no pageparts, yes?[/quote] atm yes. but it was just an example from where you can move on. i post later a more automatic Unobtrusive Ajax version. stay tuned.

#7
[eluser]Polarity[/eluser]
full update, with new code, zip download, a demo and better ajax functionality

#8
[eluser]AndrewMalachel[/eluser]
Have downloaded it...

can't wait to try it...

'll inform you how it goes... :-)

#9
[eluser]troll[/eluser]
thanks for this, i'll try it

#10
[eluser]Polarity[/eluser]
i hope its useful for someone Smile


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.