ZF2 debugging custom view helper - debugging

I a Zend Framework 2 custom view helper I use:
$uri = $this->view->vars()->mainMenu->findById('h');
The mainMenu property is a Zend\Navigation\Navigation object.
The result is that rendering of my view script stops at the point of executing the view helper without any error message. So for all practical purposes: the white screen of death.
In this view helper the line:
$uri = $this->view->vars()->mainMenu;
does work, so apparently the issue is with the findById() method.
But if I use the first line directly in my view script, I do get the expected result, a string containing the url of my home page: '/'.
My question is:
What is the issue with the findById() method in my view helper?
and/or (more importantly):
How can I debug this (and other, it is a recurring problem) issue in the view helper environment?

The Problem is that findById() doesn't exist. Check the Zend\Navigation\AbstractActionContainer which the Zend\Navigation\Navigation extends.
The correct method (i guess) would be findBy(), findAllBy() or findOneBy()
$this->view->vars()->mainMenu->findOneBy('id', 'my-id-to-find');

Found the issue by first addressing the second part of my question, by installing XDEBUG (on Zend Server CE) which finally gave some error output (calling method on non-object).
Where I was focusing on my layout view script, the same view helper also existed in my (final) view script where the navigation object was not available under the reference I used.
What works in both view and layout script is:
$uri = $this->view->layout()->getVariables()->mainNav->findById('h');
I found my solution here:
http://akrabat.com/zend-framework-2/access-view-variables-in-another-view-model/

Related

What is renderAjax(), how is it different from render()?

When I use normal return this->render('create', ['model' => $model]) my pop-up window goes all haywire. When I change to return $this->renderAjax('create', ['model' => $model]); everything is magically in their correct places. I have looked around quite a bit to read about renderAjax() but there seem to be absolutely nothing out there. Can someone tell me what it does? I know ajax but from what I know it usually has nothing to do with css or bootstrap.
To know the difference between render() and renderAjax() first you need to understand how render() works.
Basically when render() is called every piece of JS and CSS code and file references registered with the view is gathered in several arrays to be rendered later on in proper places - these places are stored in the layout and their code is rendered by calling beginPage(), head(), beginBody(), endBody() and endPage().
You can point where the JS code should be rendered by setting the second parameter in related methods - like for example:
$this->registerJs("alert()", \yii\web\View::POS_HEAD);
renders
<script type="text/javascript">alert()</script>
in layout where the method $this->head() is.
Everything is working fine until you want to render only a main part of view without the layout. Without it (and its methods like beginPage()) the JS and CSS references cannot be rendered in the previous way and that is why this fancy jQuery code rotating the square does not work - JS library has not been included there.
When you are calling $this->render() from within the view or just calling $this->renderPartial() from the controller exactly this is happening - layout is not applied.
renderAjax() comes now to the rescue.
This method doesn't care about layout because it calls beginPage(), head(), beginBody(), endBody() and endPage() methods by itself. Thanks to this every JS piece of code can be attached to the rendered view and the jQuery library can rotate this square once again even when it needs to be done inside an AJAX popup.
render() public method
Renders a view.
The view to be rendered can be specified in one of the following formats:
path alias (e.g. "#app/views/site/index");
absolute path within application (e.g. "//site/index"): the view name starts with double slashes. The actual view file will be looked for under the view path of the application.
absolute path within current module (e.g. "/site/index"): the view name starts with a single slash. The actual view file will be looked for under the view path of the current module.
relative view (e.g. "index"): the view name does not start with # or /. The corresponding view file will be looked for under the view path of the view $context. If $context is not given, it will be looked for under the directory containing the view currently being rendered (i.e., this happens when rendering a view within another view).
renderAjax() public method
Renders a view in response to an AJAX request.
This method is similar to render() except that it will surround the view being rendered with the calls of beginPage(), head(), beginBody(), endBody() and endPage(). By doing so, the method is able to inject into the rendering result with JS/CSS scripts and files that are registered with the view.
renderAjax()
render()

Joomla Terminology: view, layout, task and component development

I'm a developer and I am very confident with MVC pattern and have already developed a lot of webapp from scratch using php framework like symfony or yii.
I'm a little bit confused about joomla mvc and terminology and after googling a lot, read joomla book extensions guide, read on joomla website my doubt are still there.
What is confusing for me is the component mvc structure and how I have to set up "my way of think" about joomla mvc, for doing the things in the joomla way.
In particular I am used to reasoning in terms of controller/action (like in symfony and yii framework)
So the final list of all my webapp url will be
controller1/action1
controller1/action2
controller1/action3
controller2/action1
controller2/action2
Each controller's action will decide what view to render and what layout to use for showing the view.
In particular in these frameworks, the definition of a layout is exactly the mean of a layout. And the view is the "core part" of the page.
So I can have a view with a list of users and I can put this view inside a mobile layout or a desktop layout, or to build a view for mobile and put it only in the mobile layout and so on.
The final result about directory structure in my webapp is something similar to the following:
controllers/
controller1
controller2
controller3
models/
modelForTableA
modelForTableB
views/
controller1/
viewForAction1
viewForAction2
layouts/
mobileLayout.php
desktopLayout.php
and for me is very clear to understand.
So finally my questions are:
how would be the directory structure in joomla?
what are in joomla the definition of view, layout and task?
I need to clarify that I do not need an explaination about MVC works in general, but if I would achieve the same result as before, how I have to organize my code and my work?
Suppose that I want to build a component with the following "url"
userController/addUser
userController/editUser
userController/listUsers
userController/viewUserDetail
anotherController/addOperation
anotherController/editOperation
anotherController/myNonCrudOperation
Thank you very much
Routing in Joomla is slightly different. The SEF URLs are built from menu items, which in turn point to a View/Layout combination.
This turns things around: a controller is not bound to a specific View/Layout.
Let's make an example of the flow with the addUser functionality you mentioned as an example; I'll be referring to these files (but you'll have plenty more):
/controllers/user.php
/models/user.php
/views/useradd/view.html.php
/views/useradd/tmpl/default.php
/views/useradd/tmpl/default.xml
/controller.php
/router.php
As you can see the layouts are inside each view's tmpl folder.
router.php
Let's start from this last file: router.php defines our custom SEF rules so, after Joomla passes the call to our component (usually with the params
?option=com_componentname) we can takeover and interpret the URL as we wish. It is a bit hard to get started with but does provide the most flexibility and power. We don't really need to implement it at all for this simple example: so back to our registration now.
First step: show the "new user" form.
You would typically bind this to a menu item, pointing to the /views/useradd/tmpl/default.php; the /views/useradd/tmpl/default.xml contains the definition of the layout so it's available in the menu manager. Very often there is only one layout per view.
Control is passed to the view /views/useradd/view.html.php , and the view will then load an instance of its own model (automatically chosen based on the view name, you can load other models of course) to gather any initialization data.
The view then renders the layout, and presents it to the user.
The layout's responsibility includes generating a form with an appropriate action (endpoint) and security tokens if appropriate:
<form action="index.php?option=com_mycomponent">
<input type="hidden" task="user.save">
<?php echo JHtml::_('form.token');?>
as you see it doesn't really matter if you want to use <input or params on the url, and you can most often mix them.
Form interaction
For autocompletion the form may need to invoke some backend controller methods, i.e. the method emailAvailable() in the /controllers/user.php
It does not make sense to have such functionality indexed, so we'll invoke the method directly with a non-SEF url:
index.php?option=com_ourcomponent&task=user.emailAvailable
followed by any other parameter. This will work in both get and post.
The controller /controllers/user.php's emailAvailable() method will return a json structure and then invoke exit() as we don't want the CMS to kick in at all. An alternative solution is to add the param &format=json in the call.
{"email":"johndoe#example.com", "available":true}
Saving the data
When the user submits the form, processing is first handled by the controller since a task is specified. (see above task=user.save). Joomla will invoke the method save() in the controller /controllers/user.php.
This time, however, our controller is responsible for returning information to the user. After processing the data, it may choose to re-render the registration form showing an error, or a thank you page. In either case the controller simply sets the redirect, letting Joomla handle the rendering when appropriate.
$this->setRedirect(JRoute::_('index.php?option=com_yourcomponent&view=useradd', false));
More control
Each time a controller task is not specified, the display() method of the main controller is invoked. You can add custom logic there.
Joomla fires several events during a view rendering; these can be intercepted by a system plugin or - if you add in the calls - other kinds of plugins as well. You may even create your own types of plugins. Do not try to instantiate a view manually from a controller, as this may inhibit plugin firing.
Small insight,
1) Directory Structure
controllers/
controller1
controller2
controller3
models/
modelForTableA
modelForTableB
views/
layout1
2) View and layout and task
check this answer
3) More routing techniques with SEF.
Hope it helps.
solved with this. I cannot delete this question because there already exists other answer.
Could any moderator close or delete this? Thank you
https://joomla.stackexchange.com/questions/18774/joomla-terminology-view-layout-task-and-component-development/18799#18799

Problem with passing non-literal text to the Html.Partial() extension method

I would like to pass the file name of a partial view as data retrieved from the viewbag as such:
<div id="Zone1">#Html.Partial(ViewBag.ZoneControl1)</div>
Where the "ZoneControl1" property of the ViewBag is the name of the desired partial view retrieved from elsewhere (i.e. database, web service, etc.). If I include the text as a literal string i.e.:
<div id="Zone1">#Html.Partial("Controls/MyPartial")</div>
It works just fine. If I pass that literal string as a property of the ViewBag from the controller, or even just create a variable in the consuming view, i.e.:
#{string zone1 = "Controls/MyPartial";}
<div id="Zone1">#Html.Partial(zone1)</div>
It doesn't work. The page appears to be loading but never displays anything in the browser. Again, this works fine if I hardcode the partial view name, but not if it is passed as data from a variable or property. Anyone know why this is happening? If this is intended or unavoidable behavior, is there a workaround?
You can't use dynamic in Html.Partial (which is what ViewBag is) because it accepts only strings. One quick way around this would be to cast your ViewBag.ZoneControl:
#Html.Partial((string)ViewBag.ZoneControl1)
As for the second part (zone1 = "Controls/MyPartial") I was unable to duplicate that.
The following code is what I wrote to test it and it works just fine.
#{ string zone1 = "Controls/MyPartial"; }
<div>#Html.Partial(zone1)</div>
I assume the answer with casting the ViewBag is what you're really looking for in this case.
Well, I have it working now and I'm not exactly sure what fixed it. I copied the razor code\markup and deleted that view and created a new view and pasted in the old code. The only difference was that when I created the new view, via the wizard, I specified to NOT use a master page and the resulting page had code to specify:
#{
Layout = null;
}
The original page was created using a master page and then I changed my mind and took out the layout directive entirely. Anyway, after making those changes, it WORKED! So, I initially surmised that the reason was that a view must specify "layout = null" if not using a master page. BUT, I then took out the "layout = null" code in this new page and it still worked! So... not sure what went wrong, but to sum up:
As #BuildStarted correctly noted, you can use a property of the ViewBag object as the partial view path, but you must cast it as a string for it to work properly. So, the premise for this question was incorrect and something else was mucking things up. Just not sure what.

CodeIgniter jQueryUI dialog form example

I am trying to use CodeIgniter and jQuery-ui dialog to create a modal window with form to update user information.
The process should be like:
1. Press a button on a view page.
2. A modal window pops up.
3. Inside the window is a form that a user can fill.
4. If the user filled something before, the information should be shown in corresponding field
5. Click the update button on the modal window to save the changes to database.
Can anyone provide a good sample of this process?
I used ajax to pass the data but it didn't work when I was trying to update the data to the database. It would be nice if an example of how to pass data from ajax to php and how php handle that.
Thanks,
Milo
well the jquery bit for post(), get(), ajax() works the same in any measure you would normally use it.. key difference here is with CI you can't post directly to a file-name file-location due to how it handles the URI requests. That said your post URL would be the similar to how you would access a view file normally otherwise
ie: /viewName/functionName (how you've done it with controllers to view all along. post, get, ajax doesnt have to end in a extension. I wish I had a better example then this but I can't seem to find one at the moment..
url = '/home/specialFunction';
jQuery.get(url, function(data) {
jQuery("#div2display").html(data);
});
in the case of the above you notice despite it not being a great example that. you have the url with 2 parameters home and specialFunction
home in this case is the controller file for home in the control folder for the home file in views the specialFunction is a "public function" within the class that makes the home controller file. similar to that of index() but a separate function all together. Best way I have found to handle it is through .post() and a callback output expected in JSON cause you can form an array of data on the php side json_encode it and echo out that json_encode and then work with that like you would any JSON output. or if your just expecting a sinlge output and not multiples echoing it out is fine but enough of the end run output thats for you to decide with what your comfortable doing currently. Hopefully all around though this gives you some clairity and hopefully it works out for you.

Rails 3: #template variable inside controllers is nil

I have the same problem, as in this question. Did anybody find any solutions for this?
So I can't do like this:
flash[:notice] = "Successfully created #{#template.link_to('product', #product)}.
or like this:
#template.title("Page title is here.")
It worked perfectly in Rails 2.3. The main idea is to find out, how to use helper methods directly from conrollers, not from views.
Thanks.
You're doing it wrong.
First, you should setup the title of a page inside the view, not in your controller.
You can simply place a call to the title helper within your view file.
About the link, flash shouldn't contain HTML. However, you can create the link manually.
flash[:notice] = %Q{Successfully created product.}
I ran into this same problem as well and found that you can use the view_context method.
API documentation here: http://api.rubyonrails.org/classes/AbstractController/Rendering.html#method-i-view_context

Resources