Welcome Guest, Not a member yet? Register   Sign In
Business Logic in Nested Views/Partials
#1

[eluser]momsenmeister[/eluser]
Hi everybody,

starting with CI, I had problems to nest views within views in a clean way.
So I read a lot about it, and decided to use the following approach:
- load the basic layout-views within the controller
- within the layout-views, load partials as nested views via $this->load->view()

This works for me as long as there is no business logic involved.
But now I come to the point, where my project becomes more complex.

My question is, how I can avoid constructs like this in views:

(View: basic_layout.php)
Code:
$this->load->view('header');
$this->load->view('navigation');

if ($access == true)
{
  switch($content_to_show)
  {
    case 'startpage': ...
    case 'account': ...
    case 'impressum': ...
    default: ...
  }
}

$this->load->view('footer');

My problem here is, that I only want to define the basic layout ONCE.
So I don't want to load header, navigation and footer from the controller every time.
This should also behave the same with partials (and partials within partials etc.).
But as my views might contain loops for example, I can't just preload them in a variable in the controller.

So I more or less, all of my controllers look like this:

Code:
$data[access] = 'private';
$data['content'] = 'account';
$this->load-view('basic_layout', $data);

I don't think that it makes a lot of sense to always load the view basic_layout, but how can I avoid this in a clean way?

How do you structure complex nested views, how do you seperate the business logic?

Thanks a lot!
#2

[eluser]techgnome[/eluser]
From my controller I did this:
Code:
$data['content_view'] = 'site/mainpage';  // <-- This is the name of the view I want to display in the end
.
.
.
$this->load->view('templates/template'); // <-- this is my entry point into the template

Then inside the templates/template.php file:
Code:
$this->load->view('templates/head'); <-- Loads the head section of the page
. // More parts of the page to load
.
.
$this->load->view($content_view); // <-- This then loads the actual main content to be displayed
.// More parts of the page to load
.
.
$this->load->view('templates/footer'); // <-- loads the page footer

Clearly this is a simplistic approach, as there's a number of other pieces of data that I pass in, like the data, if the view is wide or narrow, user authentication stuff, etc.

-tg
#3

[eluser]momsenmeister[/eluser]
Thanks, techgnome!

This at least helps to avoid the switch-part.
#4

[eluser]WanWizard[/eluser]
That works if your output flow is strictly top-down.

If not ( for example, you have a message view at the top you your page, which you should obviously process last to capture all messages ), look at a template library, like the one from Colin Williams or Phil Sturgeon.
#5

[eluser]Unknown[/eluser]
It would be nice if the style of common headers/footers from this discussion were in the wiki. Compared to extending Controller class or a separate template library; nested/partial views has the advantage of simplicity by using built-in facilities.

Here's a small example I use for illustration (screen shot attached). In the Flowershop one is presented with a form and selects a color. The application responds with a list of flowers of that color. A single, common view is used for every page. This common view is handed a page title, navigation view and content view.

Here's the controller method. The view loaded is "common/default". In the array passed to the view are the title, a page navigation view and a page content view.

Code:
function flowersByColor() {
        $this->load->model('colorsModel');
        $this->load->model('flowersModel');
        $colors = $this->colorsModel->listAllColors();
        $flowers = null;
        if (isset($_POST['color_id'])) {
            $flowers = $this->flowersModel->getFlowersByColorId($_POST['color_id']);
        }
        $this->load->view("common/default", // common view for every page
            array(
                'title'=>'Flowers by Color', // page title
                'navigation'=>'flowers/nav', // page navigation view
                'content'=>"flowers/flowersbycolor", // page content view
                'colors'=>$colors, // list of colors
                'flowers'=>$flowers));  // list of flowers
    }

Here's the view common/default.php. It sets the page title, loads a page navigation view and the page content view.

Code:
&lt;?php echo doctype('html4-trans')."\n"; ?&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;
        &lt;?php echo link_tag('css/style.css')."\n";?&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;?php $this->load->view("common/banner"); ?&gt;
        &lt;?php $this->load->view($navigation); // page navigation?&gt;
        <div id="content">
        &lt;?php $this->load->view($content); // page content ?&gt;
        </div>
    &lt;/body&gt;
&lt;/html&gt;

Here is view flowers/flowersbycolor.php. It is the page content view. It displays a form to input a color and if a list of flowers is present, it loads the view flowers/tableView.php that displays the list. Note that when this view is loaded, one need not re-specify the $flowers variable for the page content.

Code:
<h2>Flowers by color</h2>
&lt;?php
echo form_open('flowers/flowersbycolor');
//convert array of objects to associative array
foreach ($colors as $color) $a[$color->color_id] = $color->color;
echo form_label('Color: ', 'color_id').form_dropdown('color_id', $a)."<br/>\n";
echo form_submit("submit", "Submit");
echo form_close();

if ($flowers) {
    $this->load->view("flowers/tableView");
}
?&gt;

Here is the view flowers/tableView.php. It displays a table of flowers. The view is shared by other controllers.

Code:
<table border="1">
    <tr>
        <th>Edit</th>
        <th>Common Name</th>
        <th>Color</th>
        <th>Season</th>
        <th>Description</th>
    </tr>
    &lt;?php  foreach ($flowers as $flower?&gt;
    <tr>
        <td>&lt;?php echo anchor("edit/".$flower->flower_id, 'edit'); ?&gt;
            &lt;?php echo "view/".$flower->flower_id, 'view'); ?&gt;
            &lt;?php echo anchor("delete/".$flower->flower_id; 'delete');
        </td>
        <td>&lt;?php echo $flower->commonname; ?&gt;</td>
        <td>&lt;?php echo $flower->color; ?&gt;</td>
        <td>&lt;?php echo $flower->season; ?&gt;</td>
        <td>&lt;?php echo $flower->description; ?&gt;</td>
    </tr>
    &lt;?php endforeach; ?&gt;
</table>

Nested, partial views can be used to create a template for pages with common headers and footers without resorting to extending controllers or separate libraries.




Theme © iAndrew 2016 - Forum software by © MyBB