ZF2 Nesting Views in View Helper - zend-framework2

I'm attempting to create a ZF2 view helper which outputs a blog post of varying display formats.
The post is made up of a header, body and footer.
I've attempted to create the view helper using the nesting example in the ZF2 docs.
// post helper
public function __invoke( PostInterface $post, $is_single = true ){
$view_model = new ViewModel();
$view_model->setTemplate( 'editorial/partials/complete' );
$view_model->setVariable( 'object', $post );
$view_model->setVariable( 'is_single', $is_single );
$body_model = new ViewModel();
$body_model->setTemplate( 'editorial/partials/xx_display_format_partial_xx' );
$body_model->setVariable( 'object', $post );
$view_model->addChild( $body_model, 'body' );
... repeat for header and footer
return $this->getView()->render( $view_model );
}
// editorial/partials/complete.phtml
echo $this->header;
echo $this->body;
echo $this->footer;
I receive no errors when echoing the view helper. The problem is, there's no output either.
Is what I'm trying to do even possible? If so, what am I doing wrong?

Try this solution https://stackoverflow.com/a/15193978/981820
It says that that PphRenderer actually does not render the child views. The tutorial shows how it works from the action point of view, and it works because in that case the view is rendered by Zend\View\View::render()
So, the solution to your problem is to render your nested views the same way it's done there.
UPDATED
Or you can do it even simpler. Just render your views separately and attach each output to your main view as a variable. See an example:
$view = new ViewModel();
$body = new ViewModel();
$header = new ViewModel();
$footer = new ViewModel();
//... some setup
$view->setVariable('body', $this->getView()->render($body));
$view->setVariable('header', $this->getView()->render($header));
$view->setVariable('footer', $this->getView()->render($footer));
return $this->getView()->render($view);
It should be the same outcome and more optimized in terms of your task. The reason why the code from the Zend\View\View::render() is more complex than this one it's because it oversees all the possible cases, but you don't have to do the same for your task.

try this :
create the child model first and then set the child model as a variable for the parent model
$body_model = new ViewModel();
$body_model->setTemplate( 'editorial/partials/xx_display_format_partial_xx' );
$body_model->setVariable( 'object', $post );
$view_model = new ViewModel();
$view_model->setTemplate( 'editorial/partials/complete' );
$view_model->setVariable( 'object', $post );
$view_model->setVariable( 'is_single', $is_single );
$view_model->setVariable( 'body', $body_model );//<-----------------------------

Related

How to use form view helper into custom view helper in zend framework 2

I am creating custom view helper. and i want to know how can i use formElement "Zend\Form\View\Helper\FormElement" in my own view helper. Here is my code.
use Zend\Form\ElementInterface;
use Zend\Form\FieldsetInterface;
use Zend\Form\View\Helper\FormElement;
use Zend\Form\View\Helper\AbstractHelper;
use Zend\View\Renderer\PhpRenderer;
class JudgeCareerViewHelper extends AbstractHelper {
private $output;
public function __invoke($formCollection) {
foreach ($formCollection as $elementOrFieldset) {
if ($elementOrFieldset instanceof FieldsetInterface) {
$obj = new FormElement();
$this->output .= $obj($elementOrFieldset->get('startServiceDate'));
} elseif ($elementOrFieldset instanceof ElementInterface) {
//set element markup
echo 'element';
}
};
echo $this->output;
die();
}
}
When i echo the output return from FormElement is empty. So i opened the zend "Zend\Form\View\Helper\FormElement" library to find out where is the problem. So i found that, below code return empty. I dont know what is the purpose of $renderer = $this->getView(); and how to get view.
$renderer = $this->getView();
if (!method_exists($renderer, 'plugin')) {
// Bail early if renderer is not pluggable
return '';
}
Purpose of creating custom view helper to generate my own markup (HTML) instead of zend buitin html.
So I found that, code $renderer = $this->getView() return empty.
You will need to ensure that the view helper is not directly instantiated using new but is called via the Zend\View\HelperPluginManager.
I suspect that the issue is because it is not correctly registered with the service manager as an invokable class.
// Module.php
public function getViewHelperConfig()
{
return array(
'invokables' => array(
'JudgeCareer'
=> 'FooModule\Form\View\Helper\JudgeCareerViewHelper',
),
);
}
This is to ensure that the Zend\View\Renderer\PhpRenderer is injected as the view.
Once the JudgeCareerViewHelper has the 'view' injected it would then be able to call other view plugins and have them loaded correctly, again via the HelperPluginManager.
The line:
$obj = new FormElement();
Should then be
$object = $this->getView()->plugin('form_element');
You may call any view helper from within your custom view helper by using
$this->getView()->anyRegisteredViewHelper();
So in your case to call the ZF2 built in form rendering view helpers you would use:
$this->getView()->formElement($element);
Whereby $element is your Form Element object (Select/Textarea/Checkbox etc)
You can of course also call explicit helpers for specific elements:
$this->getView()->formTextarea($textareaElement);

ZF2 set custom URL/route and view

I am using ZF2 as a component of another application.
I am looking for a way to set the URL and View Template of the application between an init() and a run() call. I would like a way to either modify the Request and Response objects, or regenerate them with a different URL.
I currently use ob_start() and ob_get_clean() and a view template that simply generates the_content, thus injecting the output of ZF2 inside a page of another application.
Any suggestions on methodology would be appreciated.
In Module.php you can attach event to event manager for exemple.
class Module
{
public function onBootstrap($e)
{
$eventManager = $e->getApplication()->getEventManager();
$serviceManager = $e->getApplication()->getServiceManager();
$eventManager->attach(MvcEvent::EVENT_ROUTE, function($e) use ($eventManager, $serviceManager){
// your code here
}, -1000);
}
}
Or your action in your controller can dispatch another action and get the result
in action method :
$return = $this->forward()->dispatch('controllerName', array('action' => 'actionName', 'param1' => 'value', ...));
The following code inside another application can be used to set the calling URL and View Template from outside of the application:
$bootstrap = \Zend\Mvc\Application::init( include( '/zf2/config/application.config.php' ) );
$event = $bootstrap->getMvcEvent( );
/* Modify the event with a custom request. */
$request = new \Zend\Http\Request( );
$request->setMethod( \Zend\Http\Request::METHOD_GET );
$request->setUri( $custom_url );
$event->setRequest( $request );
/* Modify the view. */
$event->getViewModel()->setTemplate('layout/custom-layout');
ob_start( );
$bootstrap->run( );
$html = ob_get_clean( );

Multiple view strategy in zend 2 [duplicate]

So far, I have figured out how to return a typical JSON response in Zend Framework 2. First, I added the ViewJsonStrategy to the strategies section of the view_manager configuration. Then, instead of returning a ViewModel instance from the controller action, I return a JsonModel instance with all my variables set.
Now that I've figured that piece out, I need to understand how to render a view and return it within that JSON response. In ZF1, I was able to use $this->view->render($scriptName), which returned the HTML as a string. In ZF2, the Zend\View\View::render(...) method returns void.
So... how can I render an HTML view script and return it in a JSON response in one request?
This is what I have right now:
if ($this->getRequest()->isXmlHttpRequest()) {
$jsonModel = new JsonModel(...);
/* #todo Render HTML script into `$html` variable, and add to `JsonModel` */
return $jsonModel;
} else {
return new ViewModel(...);
}
OK, i think i finally understood what you're doing. I've found a solution that i think matches your criteria. Though i am sure that there is room for improvement, as there's some nasty handwork to be done...
public function indexAction()
{
if (!$this->getRequest()->isXmlHttpRequest()) {
return array();
}
$htmlViewPart = new ViewModel();
$htmlViewPart->setTerminal(true)
->setTemplate('module/controller/action')
->setVariables(array(
'key' => 'value'
));
$htmlOutput = $this->getServiceLocator()
->get('viewrenderer')
->render($htmlViewPart);
$jsonModel = new JsonModel();
$jsonModel->setVariables(array(
'html' => $htmlOutput,
'jsonVar1' => 'jsonVal2',
'jsonArray' => array(1,2,3,4,5,6)
));
return $jsonModel;
}
As you can see, the templateMap i create is ... nasty ... it's annoying and i'm sure it can be improved by quite a bit. It's a working solution but just not a clean one. Maybe somehow one would be able to grab the, probably already instantiated, default PhpRenderer from the ServiceLocator with it's template- and path-mapping and then it should be cleaner.
Thanks to the comment ot #DrBeza the work needed to be done could be reduced by a fair amount. Now, as I'd initially wanted, we will grab the viewrenderer with all the template mapping intact and simply render the ViewModel directly. The only important factor is that you need to specify the fully qualified template to render (e.g.: "$module/$controller/$action")
I hope this will get you started though ;)
PS: Response looks like this:
Object:
html: "<h1>Hello World</h1>"
jsonArray: Array[6]
jsonVar1: "jsonVal2"
You can use more easy way to render view for your JSON response.
public function indexAction() {
$partial = $this->getServiceLocator()->get('viewhelpermanager')->get('partial');
$data = array(
'html' => $partial('MyModule/MyPartView.phtml', array("key" => "value")),
'jsonVar1' => 'jsonVal2',
'jsonArray' => array(1, 2, 3, 4, 5, 6));
$isAjax = $this->getRequest()->isXmlHttpRequest());
return isAjax?new JsonModel($data):new ViewModel($data);
}
Please note before use JsonModel class you need to config View Manager in module.config.php file of your module.
'view_manager' => array(
.................
'strategies' => array(
'ViewJsonStrategy',
),
.................
),
it is work for me and hope it help you.
In ZF 3 you can achieve the same result with this code
MyControllerFactory.php
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$renderer = $container->get('ViewRenderer');
return new MyController(
$renderer
);
}
MyController.php
private $renderer;
public function __construct($renderer) {
$this->renderer = $renderer;
}
public function indexAction() {
$htmlViewPart = new ViewModel();
$htmlViewPart
->setTerminal(true)
->setTemplate('module/controller/action')
->setVariables(array('key' => 'value'));
$htmlOutput = $this->renderer->render($htmlViewPart);
$json = \Zend\Json\Json::encode(
array(
'html' => $htmlOutput,
'jsonVar1' => 'jsonVal2',
'jsonArray' => array(1, 2, 3, 4, 5, 6)
)
);
$response = $this->getResponse();
$response->setContent($json);
$response->getHeaders()->addHeaders(array(
'Content-Type' => 'application/json',
));
return $this->response;
}
As usual framework developer mess thing about AJAX following the rule why simple if might be complex Here is simple solution
in controller script
public function checkloginAction()
{
// some hosts need to this some not
//header ("Content-type: application/json"); // this work
// prepare json aray ....
$arr = $array("some" => .....);
echo json_encode($arr); // this works
exit;
}
This works in ZF1 and ZF2 as well
No need of view scrpt at all
If you use advise of ZF2 creator
use Zend\View\Model\JsonModel;
....
$result = new JsonModel($arr);
return $result;
AJAX got null as response at least in zf 2.0.0

How can I avoid duplicating this grid config code?

I have the following code that is used in a Razor view to configure grid settings for a DevExpress GridView MVC extension. All is good with the code, but now I wish to do data exports from the grid, which require the same configuration code on the 'server', i.e. upstream of the view. I could quite easily do this and provide a GridSettings property on my view model, if it were not for the required access to the WebViewPage<TModel>.ViewContext property.
Right now I am using a really ugly workaround and passing ViewContext back into the controller from the view; the controller then builds the grid settings. Needless to say the view calling a method on the controller is rather smelly.
settings.Columns.Add(column =>
{
column.Caption = "#";
column.SetDataItemTemplateContent(c =>
{
ViewContext.Writer.Write(
Html.ActionLink("Edit", "Edit", new {id = DataBinder.Eval(c.DataItem, "Id")}) + "&nbsp" +
Html.ActionLink("Delete", "Delete", new {id = DataBinder.Eval(c.DataItem, "Id")},
new {onclick = "return confirm('Do you really want to delete this record? [Just say no!]')"})
);
});
column.SetHeaderTemplateContent(c => ViewContext.Writer.Write(Html.ActionLink("New", "Create")));
column.Settings.AllowDragDrop = DefaultBoolean.False;
column.Settings.AllowSort = DefaultBoolean.False;
column.Width = 70;
});
settings.Columns.Add("RefNum", "Emp. No.");
In general, it is necessary to have only the "Name" property of the exported GridViewSettings object on both the PartialView and Controller sides.
The GridView's PartialView should also be wrapped with a form.
See this example in the DX code library and this thread.
It is possible to specify shared GridViewSettings on the Controller side within a static object (like in this demo).

Generate hyperlink in ASP.NET MVC 2 controller?

I've been scouring the web for a way to do this.
I want to generate a hyperlink to an action from my controller and put it in a string. I need to be able to define the label and give it html attributes. I can get Url.Action(...) working but that method doesn't let me define the label on the link.
HtmlHelper.GenerateLink(...) looks promising but I can't find any concrete examples on how to use it.
The link should look something like this:
View
Add this property to your base controller:
protected HtmlHelper Html
{
get
{
var viewContext = new ViewContext( ControllerContext, new WebFormView( Request.CurrentExecutionFilePath ),
new ViewDataDictionary(), new TempDataDictionary(), Response.Output )
{
RouteData = ControllerContext.RouteData
};
return new HtmlHelper( viewContext, new ViewPage() );
}
}
and then call it from anywhere:
var link = Html.ActionLink( "Click Me", "action" );
try this
string str = string.Concat("View"
and then pass this in ViewData and call it in view
<%= str%>
there are a few ways to do this - here are 2:
Link name here
Html.ActionLink(article.Title,
"Login", // <-- Controller Name.
"Item", // <-- ActionMethod
new { id = "<arguments here" }, // <-- Route arguments.
null // <-- htmlArguments .. which are none. You need this value
// otherwise you call the WRONG method ...
// (refer to comments, below).
)
there are other overloads of each available
Perhaps a little more information on why you would want to do this would be a little more helpful. If you return a string that contains HTML it will by default be HTML encoded and rendered useless on the client. If you have a custom view where this will be rendered why not build the link there using #Html.ActionLink?
I guess I am trying to figure out the benefit of doing it in the controller rather than the view...

Resources