I want to create a navigation for Application module as the main navigation containing all module, and a navigation for each others modules containing all controllers of this module.
It will rendered at the last like tabs with subs tabs depending of the active page.
I want to do this with child layout, without inserting $view->layout()->addchild(..) in each action of each controllers of each module.
In each Module's Module.php file you can attach a custom event in the onBootstrap method to set whichever template you wanted:
//Attached in the onBootstrap method of Module.php
public function determineLayoutEvent(\Zend\Mvc\MvcEvent $event) {
$view = new \Zend\View\Model\ViewModel();
$view->setTemplate('custom/custom_layout');
$event->setViewModel($view);
}
I would do something like that^^.
There might be a hiccup or two with the code I've given when appending the actual view from the controller, but this should be a decent start.
Related
I'd like to have the layout reflect some data from a model. However, the render method from the CController class passes the structured data only to the view file, while the layout file only gets the rendered view passed.
So, how to best have the layout display data from a model?
Two possibilities come to mind:
Make Yii's layout file a no-op, mimicking layout logic manually from the view.
Override CController's render method in its subclass.
I'm not so happy with either variant, so maybe someone has a cleaner idea on how to do it?
Another way is to define a public variable in your controller class, something like:
class MyController extends Controller {
public $test = 'foo';
....
That value can then be accessed within a layout:
echo $this->test;
And manipulated in an action:
public function actionMyaction(){
$this->test = "bar";
...
Obviously it's not ideal if you have many variables that you need to use in a layout. One solution is to use an array of parameters. Alternatively you could look at making your layout more minimal and using CWidget to create reusable components for use inside your views.
For example, you obviously wouldn't want to have the code for your main navigation duplicated inside every view, so the obvious solution is to have in the layout, but if it becomes inconvenient to handle the data you could have an instance of a widget that renders out the navigation inside each view (and you can pass data to the CWidget class) something like:
$this->widget("MainNavigation",array("params"=>$params));
I'm having a strange issue with Yii and a theme. I set it in config/main.php like:
'theme'=>'themeName',
as usual. But when I try to render a view, it is rendered as is, without any layout, as if I called:
$this->renderPartial
I double check that I don't call for renderPartial, the themes seem to be equal to all the others theme I've done. What can be this issue about?
Thank's for any help, I'm going out of mind on this...
Here is the structure and syntax that you should have to check
-yiiroot
-!-!protected
-!-!-!controllers
-!-!-!-!TestController.php
-!-!themes
-!-!-!themeName (it was the one that you have set on config file)
-!-!-!-!views
-!-!-!-!-!layouts
-!-!-!-!-!-!main.php // It would be default what if public $layout has not been overwriten or the layout file which has been set was not found
-!-!-!-!-!test
-!-!-!-!-!-!viewName.php
On controller TestController
public $layout is main as default or is overwritten there
in actionIndex you set $this->render('viewName');
If you rendered your page by method renderPartial() directly in controller, you would not get the layout template for sure
render() is commonly used to render a view that corresponds to what a
user sees as a "page" in your application. It first renders the view
you have specified and then renders the layout for the current
controller action (if applicable), placing the result of the first
render into the layout. It then performs output processing (which at
this time means automatically inserting any necessary tags
and updating dynamic content) and finally outputs the result.
renderPartial() is commonly used to render a "piece" of a page. The
main difference from render() is that this method does not place the
results of the render in a layout. By default it also does not perform
output processing, but you can override this behavior using the
$processOutput parameter.
renderFile() is a low-level method that does the grunt work of
rendering: it extracts the data variables in the current scope and
then runs the view code. The other two methods internally call this
one, but you should practically never need to call it yourself. If you
do, keep in mind that you need to pass in a file path (not a view
path).
Reference: Yii difference between rendering functions
I'm creating a single-page web app that has one controller for the overall page (PageController) and separate child controllers for two views (ViewController and EditController).
ViewController needs a button called "Edit" in the titlebar of the app, EditController needs a button called "Save". The buttons occupy the same space, but have different labels and different on-click handlers. The titlebar belongs to the parent template/controller (i.e. PageController) scope.
One way to accomplish this is to create the button in the parent scope and let the child controllers change the text and override the ng-click handler - but I'm thinking there's probably a better way with Angular. I'd like some way for the child controllers to "inject" (not sure if this is the proper use of the word here) their button into to the parent template and handle the onclick locally, making the parent agnostic of what goes on in the child controllers...
I would think about your "views" differently. To me, titlebar is a view, just like your View and Edit views. It should therefore either contain all of the HTML it needs to render whatever you might want to show in that view, or it should know which files to ng-include.
Views are driven by models. The View and Edit controllers should call methods defined on whatever controller (or service) contains the titlebar model to set some state/properties appropriately. The titlebar view/HTML would use ng-show/hide or ng-include directives to show/include the appropriate HTML based on the current state of the model/$scope.
To be notified of a button click, the View and Edit scopes could $watch a model/$scope property for a change. E.g., <a ng-click="buttonState.clicked=true">...</a> I'm using an object with a clicked property so that the child controllers can reset the value inside their $watch callbacks (if a primitive was used, resetting would not work -- a new child scope property would be created):
$scope.$watch('buttonState.clicked', function() {
buttonState.clicked = false
... handle button click here ...
}
I would like to make a layout with a sidebar that can have widgets from different modules. Lets say there shall always be a login widget at the top if the user isn't logged in then it shall show user info. The getting started album guide could use it to display the latest albums and so on, i hope you understand how i want to use the sidebar.
Could it be done with a config file in autoload and a small code that read that config and calls the widgets on every page load?
There are several ways of page composition in Zend Framework 2:
1. Switching between Layouts
By default, ZF2 provides you with a single layout template layout.phtml.
In real-life applications, you will probably need to have several layouts
and switch the layout for certain controller/action. In each of your layouts, you will be able to show different widgets/sidebars.
2. Partial Views
A partial view is a .phtml view template file which can be rendered by another
view template. Partial views allow to compose your page of pieces and reuse pieces
of view rendering logic across different view templates. This is accomplished through the Partial view helper.
3. Placeholder View Helper
The Placeholder is another useful view helper allowing for capturing HTML
content and storing it for later use. Thus, analogous to the Partial
view helper, it allows to compose your page of several pieces.
4. Forward Controller Plugin
With the Forward controller plugin, you are able to call an action (for example, the action rendering some widget) from another module/controller from your controller and grab the output of that action. Then you are able to incorporate that output into your page.
5. Use View Models for Page Composition
When you write action methods for the controller classes, you use the ViewModel
class as a variable container for passing the variables from controller to view template,
and for overriding the default view template name. But, actually the ViewModel class is more than just a variable container plus view template name. In fact, it is closely related to the layout and page composition.
The third big capability of the view model class is that it allows for combining several
view models in a tree-like structure. Each view model in the tree has the associated
view template name and data variables that can be passed to the view template to control
the process of rendering.
This feature is internally used by Zend Framework 2 when "combining" the layout view template and the view template associated with the controller's action method. ZF2 internally creates the view model for the layout template and assigns it with layout/layout view template name. When your controller's action method returns the ViewModel object, this object is attached as a child to the layout view model.
So, you can attach your own view models to the default view model to render the page of pieces that you want.
I have a form I need to show on every page. I'd like to put it in the layout rather than defining it in multiple controllers and view templates. I'm not sure how to do this without creating a slot for it, but then I have to define the slot in every template, and I'm back at square one.
My other thought would be to create a custom action class that defines the form and then subclass all my other actions from it, but that seems like overkill.
You could just use a component, easier than a slot, and stick that in your template, only needs to be defined in one place:
<?php include_component('someModule', 'someAction') ?>
I use components and partials in my layouts quite a bit, works well.