help with view within a view

#1
[eluser]matches[/eluser]
Hello, I am trying to load a view within a view and having some trouble.

I want to load this Location Selector within another view.

Location Selector Controller
Code:
<?php

class locationSelector extends Controller {
    
    function __construct()
    {
        parent::Controller();
        
        $this->load->database();
        $this->load->helper(array('form', 'url'));
    }
    
    function index()
    {
        $venueCountries = "SELECT * FROM cities ORDER BY country, city";
        $venueStateProvence = "SELECT * FROM cities ORDER BY state_provence";
        $venueCity = "SELECT * FROM cities ORDER BY city";
        $venues = "SELECT * FROM venues ORDER BY venue";
        
        $data['venueCountries'] = $this->db->query($venueCountries);
        $data['venueStateProvence'] = $this->db->query($venueStateProvence);
        $data['venueCity'] = $this->db->query($venueCity);
        $data['venues'] = $this->db->query($venues);
                
        $this->load->view('locationSelector/index', $data);
    }
}

?>

Location Selector View
Code:
<select>
                    <option>Select Venue</option>
                    &lt;?php foreach($venues->result() as $row): ?&gt;                                    
                    <option>&lt;?= $row->venue ?&gt;</option>                
                    &lt;?php endforeach; ?&gt;
                </select>
                <select>
                    <option>Select Country</option>
                    &lt;?php foreach($venueCountries->result() as $row): ?&gt;                                    
                    <option>&lt;?= $row->country ?&gt;</option>                
                    &lt;?php endforeach; ?&gt;
                </select>
then I trying to load it within this view

Quote:&lt;?php $this->load->view('/locationSelector/index'); ?&gt;

Code:
&lt;?php $this->load->view('header/index'); ?&gt;
        <div id="content">            
            <div id="rightColumn">
                &lt;?php $this->load->view('/locationSelector/index'); ?&gt;    
            </div>
            <div id="leftColumn">
            
            </div>
            <div id="centerColumn">
            &lt;?php foreach($blogEntries->result() as $row): ?&gt;
            <div class="blogEntry">
                <h2><a >id ?&gt;">&lt;?= $row->title ?&gt;</a></h2>
                <h3>&lt;?= $row->category ?&gt;/&lt;?= $row->subCategory ?&gt;</h3>
                <p>&lt;?= $row->body ?&gt;</p>
                &lt;?php
                    $time = mysql_to_unix($row->entryTime);
                    $datestring = "%Y %m %d";
                    echo mdate($datestring, $time);
                ?&gt;
            </div>
            &lt;?php endforeach; ?&gt;
            </div>        
            <div style="clear: both;"></div>
        </div>
        &lt;?php $this->load->view('footer/index'); ?&gt;

When I view the page. I just begins the selection and fails before it fills in any data.

Any ideas what I am do

#2
[eluser]jedd[/eluser]
Views from within views got me tied in knots, so I went down this path:

[url="http://ellislab.com/forums/viewthread/106945/#538402"]http://ellislab.com/forums/viewthread/106945/#538402[/url]

You load your sub-views from within your controller, using the third parameter of load->view as TRUE - this forces the load->view to return the data (rather than, well, viewing it) back to a variable. You can then pass those variables out to your main view - which can be quite small, much like your layout template above, full of DIV's that pretty much contain just php echos.

Does this make sense?

#3
[eluser]tzultacah[/eluser]
just a thought.....

from what it looks like, you are going to have to include headers and footers on each view file you create. There are ways around this.

For an example... I have created a Layout library (specific to what I am doing) that handles all of that. You can create different layout views that include headers and footers without having to include them on each view page.

#4
[eluser]bigtony[/eluser]
I've found this simple approach works for me:

Controller: somepage.php
Code:
&lt;?php

class Somepage extends Controller {

  function Somepage() {
    parent::Controller();    
  }

  function index() {
    $view_data['title'] = 'Title of page';
    $view_data['h1'] = 'H1 page header text';
    
    $view_data['somedata'] = 'Some data for the page;
    
    $view_data['view_template'] = 'somepage_view';
    $this->load->view('layout_view', $view_data);
  }

}

?&gt;

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

&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;?php if (isset($h1)): ?&gt;
      <h1>&lt;?php echo $h1; ?&gt;</h1>
    &lt;?php endif; ?&gt;
    
    // following line loads the content specific to this page.
    &lt;?php echo $this->load->view("{$view_template}"); ?&gt;

    // other stuff can go here that appears on all pages, eg. page links.
  &lt;/body&gt;
&lt;/html&gt;

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

<p>&lt;?php echo $somedata; ?&gt;</p>

As you can see, each controller sets a value in the 'view_data' array with the name of the view specific to that page. Controller then calls 'layout_view' to take care of the headers, footer, etc. common to each page, and this view in turn calls the specific page view as per the 'view_data' variable value. All data in view_data is cascaded to each view automatically.

Obviously above example is bare-bones just to show the principle. It's not a perfect mvc solution as you end up putting display text in the controller (eg. title), but it's simple and it works.

#5
[eluser]tzultacah[/eluser]
Since we are having more discussion on this topic, I wanted to explain my thoughts a little more thoroughly.

My Goal was this:
* have basically the same header/footer for each "page", and maybe some pages won't have the same layout.
* have these headers/footers included and parsed without having to specifically tell the code to do so for pages that all use the same layout.

Let me paste some code in here to start and then I'll explain.....

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

/**
* layout class to handle css, javascript, headers (kinda) and the type of layout we want to use.
*/

class Layout {

    private $obj               = null;
    public $layout             = array();
    public $media              = array();
    public $menu_bar           = array();
    public $header             = array();

    function __construct($layout = '') {
        $this->obj                      = get_instance();
        $this->layout                   = $layout;

        // take note of these next three lines for now, I'll explain when I get to the main view layout
        $this->media['js']['scripts']   = array();
        $this->media['js']['onloads']   = array();
        $this->media['css']             = array();
        
        $this->_setMenuBarData();
        $this->_setHeader();
    }

    function view($view, $data = null, $return = false) {
        // for codeigniter version 1.7.0
        if (trim($this->layout) == '') {
            $this->layout = 'layouts/main';
        }
        $return_layout = false;

        $this->obj->load->helper('html');

        $controller             = get_class($this->obj);
        $model                     = ucwords($controller);
        $layout['menu_bar']     = $this->menu_bar;
        $layout['header']       = $this->header;
        $layout['media']        = $this->media;

        $layout['controller']   = $this->obj->router->fetch_class();
        $layout['action']       = $this->obj->router->fetch_method();

        $this->_parseSideBar($layout);
        
        $layout['content']      = $this->obj->load->view($view, $data, true);
        $layout['base_url']     = base_url();
        
        $data['layout']         = $layout;

        if ($return) {
            return $this->obj->load->view($this->layout, $data, true);
        } else {
            $this->obj->load->view($this->layout, $data, false);
        }
    }

    public function _setMenuBarData() {
        $this->menu_bar = array(
            'Home'          => base_url(),
            'Page 1'        => 'whatever_controller/page1',
            'Page 2'        => 'whatever_controller/page2');
    }
    
    public function _setHeader() {
        $this->header = array(
            'title' => 'Title for the link',
            'link'  => base_url(),
        );
    }
    
    private function _parseSideBar(&$layout) {
        $nav = array(
            'Stuff'    => array(
                1   => array(
                    'title' => 'Stuff',
                    'link'  => 'stuff_contoller/some_stuff'));
        $layout['nav'] = $nav;
    }
}
?&gt;
For the Layout lib to work, you will have to load it in your controller library... (for me this is the MY_Controller lib that I have extended)
--snipit--
Code:
class MY_Controller extends Controller {
    
    public $namedArgs       = null;
    public $router          = null;
    private $xajax_methods    = array();
    
    public function __construct() {
        parent::Controller();
        // here is the line you need
        // by default, we are using the "main" layout in the views/layouts/ directory,
        // main.php view file just like all other views
        $this->load->library('layout', 'layouts/main');

The view is in my next post

#6
[eluser]tzultacah[/eluser]
The main.php layout view:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
&lt;html&gt;
&lt;?php
    $base_url = $layout['base_url'];
?&gt;
&lt;head&gt;
    &lt;meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/&gt;
    &lt;meta name="description" content="content blah blah"/&gt;
    &lt;meta name="keywords" content="keywords n stuff"/&gt;
    &lt;meta name="author" content="ME!"/&gt;
    &lt;base href="&lt;?php echo $base_url;?&gt;"/&gt;
    &lt;link rel="icon" type="image/x-icon" href="app/img/favicon.ico" /&gt;
    &lt;link rel="stylesheet" type="text/css" href="app/css/grey-black.css" media="screen"/&gt;
    &lt;link rel="stylesheet" type="text/css" href="app/css/grey-black-main.css" media="screen"/&gt;
    &lt;link rel="stylesheet" type="text/css" href="app/css/messages.css" media="screen"/&gt;
&lt;?php
    // now you can specify additional css for ... down to even the function of a controller
    foreach($layout['media']['css'] as $css_file) {
?&gt;
    &lt;link rel="stylesheet" type="text/css" href="&lt;?php echo $css_file; ?&gt;" /&gt;
&lt;?php
    }
    // same here with the javascript. If you have a controller function that needs additional
    // javascript, you can assign it to ONLY that controller function/view
    foreach($layout['media']['js']['scripts'] as $script_name) {
?&gt;
    [removed][removed]
&lt;?php
    }
?&gt;
    [removed][removed]
    &lt;title&gt;Title&lt;/title&gt;
&lt;/head&gt;

&lt;!-- zero margin = wide layout --&gt;

&lt;body style="margin: 0;"&gt;
&lt;!-- CONTAINTER --&gt;
    <div class="container">
        <div class="header">
&lt;!-- this is actually where I have my header stuff, you could just include a header.php
view and shove all this code in there --&gt;
            &lt;?php echo html_link('<span>'.$layout['header']['title'].'</span>', $layout['header']['link'], array(), false, false); ?&gt;
        </div>
        <div class="stripes"><span></span></div>
&lt;!-- Top menu bar --&gt;
        <div class="nav">
&lt;?php  
    if (checkArray($layout['menu_bar'])) {
        foreach ($layout['menu_bar'] as $title => $url_seg) {
            echo html_link($title, $url_seg, array(), false, false)."\n";
        }
        if (isset($layout['user']) && checkArray($layout['user'])) {
            echo '<div style="text-align:right;padding:7px;">Welcome '.$layout['user']['username'].'</div>';
        }
    } else {
        echo html_link('Home', $base_url, array(), false, false());
    }
?&gt;
            <div class="clearer"><span></span></div>
        </div>
&lt;!-- END Top menu bar --&gt;
        <div class="stripes"><span></span></div>
        <div class="main">
            <div class="left">
&lt;!-- CONTENT --&gt;
                <div class="content">
&lt;?php // flashdata used with redirects with session information.... errors etc ?&gt;
&lt;?php include 'flashdata.php'; ?&gt;
&lt;?php // and here you echo your view file for the controller of the page you are accessing ?&gt;
&lt;?php echo $layout['content']; ?&gt;
                </div>
&lt;!-- END CONTENT --&gt;
            </div>
&lt;!-- RIGHT NAV --&gt;
            <div class="right">
                <div class="subnav">
&lt;?php include('right_nav.php'); ?&gt;
                </div>
            </div>
&lt;!-- END RIGHT NAV --&gt;
            <div class="clearer"><span></span></div>
        </div>
&lt;!-- FOOTER --&gt;
        <div class="footer">
&lt;?php include('footer.php'); ?&gt;
        </div>
&lt;!-- END FOOTER --&gt;
    </div>
&lt;!-- END CONTAINTER --&gt;
&lt;/body&gt;
&lt;/html&gt;

The final step is in your controllers
--snipit--
Code:
class Users extends MY_Controller {

    var $sidebar    = array(
    );
    public function __construct() {
        parent::__construct();
                // this is needed in each controller, basically -- if you have used a different
                // layout somewhere, this sets it back to the main one.
        $this->load->library('layout', 'layouts/main');
Now in my "page" function, I use:
Code:
public function index() {
        $data = array();
        
        $this->layout->view('users/index', $data);
    }

Ok so.... how does all this benefit me?
here we go.
1. Now you have a site layout, with headers, footers, side content ... whatever you want
2. All of these parts and pieces are included without having to tell each page to do so.
3. If (for example) the "display" page of users (function display) needs a different layout, all you have to do is tell that function to use a different layout (which you have to define of course) like so:
Code:
public function display() {
        $this->layout->layout = 'layouts/plain';

*Note: I do believe I have broken some MVC principles here with using raw includes to files in a "view" file, but this solution has been very clean, and we're not calling controller functions or anything fancy here in the included files. All data needed for them is fed to them accordingly. They are view files, and this is a means of setting up a solid layout without trying to set content for "static views" each time you want to use them.


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


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