Packages and rendring view from controller

Permalink 1 user found helpful
I'm trying to render different views from one controller.

My setup:
Controllers:
flash_catalog/controllers/dashboard/flash_catalog/manage_flash

Views:
flash_catalog/single_pages/dashboard/flash_catalog/edit_flash
flash_catalog/single_pages/dashboard/flash_catalog/list_flash

on DashboardFlashCatalogManageFlashController class in edit_flash method
I try to call list_flash view to render like this
$this->render('/flash_catalog/single_pages/dashboard/flash_catalog/edit_flash');
I got only empty page.

I have work around for this creating controller for every view, but is it the right way?

 
jordanlev replied on at Permalink Reply
jordanlev
As far as I can tell, there is a very severe limitation in C5's MVC and routing system that makes it impossible to do what you want here. One controller corresponds to one view, and they must both have the same name (or be in directories with the same name if you want to call the files "view.php" and "controller.php").

Seems that the way to implement different views for the same controller is to put it all in one view file and have a big "if" statement based on $this->controller->getTask() . Very unfortunate if building a system of any complexity (more than 2 pages). I believe this was a design decision to try to keep things simple for the simple cases. Unfortunately it makes the complex things really hard to write cleanly.
jordanlev replied on at Permalink Reply
jordanlev
Hold on a sec -- I think I just figured it out! It's a bit of a hack, but should work.

You want the controller to be here:
flash_catalog/controllers/dashboard/flash_catalog/view.php

and the controller class name should be "DashboardFlashCatalogController"

The views can be here:
flash_catalog/single_pages/dashboard/flash_catalog/edit_flash.php
flash_catalog/single_pages/dashboard/flash_catalog/list_flash.php

But here's the trick:
You want to have one default view template (flash_catalog/single_pages/dashboard/flash_catalog/view.php), and all of the other view files are for specific actions in your controller. This way you only install one single page to the site (at the path "dashboard/flash_catalog") -- if you install more, then the system looks for different controllers (which you don't want -- you want the one controller handling all requests to this section).

And here's the other trick:
At the end of each action method inside your controller file (besides view(), which will work just fine automatically), call $this->render() in the exact right way. For edit_flash, it's this:
$this->render('/dashboard/../../../packages/flash_catalog/single_pages/dashboard/flash_catalog/edit_flash');

and for list_flash, it's this:
$this->render('/dashboard/../../../packages/flash_catalog/single_pages/dashboard/flash_catalog/list_flash');


Like I said, it's super hacky. Note that you only need to put in this ridiculous render path if you're in a package. If instead you're just putting single_pages and controllers into your site's top-level directories (so not inside the packages directory), you could just pass a path like this to the render() function:
$this->render('/dashboard/flash_catalog/edit_flash');
jjgdenisrobert replied on at Permalink Reply
A simpler solution is to turn view.php into a dispatcher, and to include in that file just the code to select the view you want, using include(). Here's one of my view.php files:


switch($this->controller->getTask()) {
case 'update':
case 'edit':
include('edit.php');
break;
case 'add':
include('add.php');
break;
default:
include('default.php');
}
jordanlev replied on at Permalink Reply
jordanlev
Also note that I fixed this issue in the core code so as of Concrete5.5 you can include different view templates from a single_page controller in a package just like you could before from site-level single_pages. So the OP's original code:
$this->render('/path/to/template')

...will work now in 5.5+