zendframework / zend-expressive-zendviewrenderer

zend-view PhpRenderer integration for Expressive
BSD 3-Clause "New" or "Revised" License
11 stars 12 forks source link

optionally disable layout rendering #23

Closed pine3ree closed 7 years ago

pine3ree commented 8 years ago

I haven't found a way to disable layout rendering other than creating a layout none.phtml containing just <?=$this->content?>....not very elegant even if it works.

Disabling the layout (setTerminal(true) in zend view model terminology) can be useful when handling ajax requests. In most cases I use a JsonResponse, but sometimes an HtmlResponse is needed.

We could use the value false for the $layout template parameter to make the renderer skip the preparation of layout, because once it's added via its constructor - as far as I know - you can only change it to a different layout.

Additional notes:
vaclavvanik commented 7 years ago

You should add tests

weierophinney commented 7 years ago

I would like to merge this, but I cannot figure out from the code how it works, exactly; unit tests would help a ton in understanding your expected use case.

pine3ree commented 7 years ago

Hello @weierophinney ,

I will add some tests in the next days. I first wanted to make sure this feature is useful to others and sufficiently elegant (I am not sure it is, zend-view is as setTerminal() is very clear and explicit). You are right...it's usage is not evident from the patch....everything appears so clear in the same instant you are digging into the problem....

just a couple of examples to disable layout decorated rendering:

// 1. set the $layout variable globally (TemplateRendererInterface::TEMPLATE_ALL)
if ($isAjaxRequest) {
    $this->view->addDefaultParam('*', 'layout', false);
}

return new HtmlResponse(
    $this->view->render('blog::post/index', [
        // tpl vars here
    ]);
);

// 2. set the $layout var for the current tpl only
return new HtmlResponse(
    $this->view->render('blog::post/index', [
        'layout' => false,
        // tpl vars here
    ]);
);

the special value false is the key to disable layout rendering. Setting globally seems a little clearer because it can be called independently and conditionally just before rendering occurs, but the final result would be the same in this case.

In this example a standard request would for instance render the 1st page of blog articles in an admin area. Ajax calls (with specific page/sort/filter params) would trigger updates of an article list section only. Returning a json object with the current article list data / pagination links data and rebuilding the html via javascript (mithril/vue) would be the most modern way to do it, but i believe that ajax html partials are still commonly utilized.

Of course a special method $this->view->disableLayout() implemented for zend-view, plates, twig would be preferrable...but I am not sure this make sense in twig (where we call the internally processed {% extends "layout.twig" %} tag) or in plates (where we apply a layout by explicitly calling $this->layout('layouts::main') inside the template).

kind regards

(updated) In the examples $this->view is an instance of the view renderer.

vaclavvanik commented 7 years ago

ping @weierophinney

weierophinney commented 7 years ago

Thanks, @pine3ree; merged to develop for release with 1.3.0.