Why ajax calls doesn't load the layout in CakePHP 2.3 - cakephp

I am wondering why if i use jquery $.load function or some pluging such as fancybox to load content dynamically on the site, the layoug is not loaded but only the view as if it were an element.
My $.load() calls a controller action as if it was a normal link, like:
$('#demo').load("http://"+ document.domain +"/tables/users/edit/", {input : data}, function(dat){
//whatever
});
This is not something I personally dislike, like this I avoid creating elements and calling them using $this->render('/Elements/xxxx', false); from my controllers.
I want to know if this is the proper way to work with or if it is some kind of cheat or bug of cakephp.
How should we treat this type of content which is not a proper "view" (as won't have a layout, headers...etc), but an "element" loaded dynamically? As a view? As an element?
Thanks.

Check /Layouts/ajax.ctp this is the layout that is rendered for ajax calls. Usually you don't want to have all the header and footer around the element you request when doing an ajax call.

Burzum is on the right track.
Your controller will load the default layout unless you tell it to use /Layouts/ajax.ctp. So in your edit function you'd want to switch layouts depending on how the function is being called. For example:
if($this->request->is('ajax')){
$this->layout = 'ajax';
}// else use controller default...or specify another layout to use here.

Related

Angular - different route, same template/controller,different loading method

I want to use routes, but I always want to use same template & controller. I have routes like this:
**a/:albumid**
and
**i/:imageid**
In the first case I want to load an array of images and add them to a list. In the second case I want to load a single image and add it to a list.
So the difference is only in data loading. What is the most efficient way to do this?
Also is it possible to animate ng-show? Something like jQuery's slideDown?
Check out this article, it describes a way to do exactly what you want:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
I've used the technique, it works well.
In a nutshell, something like this for routing:
$routeProvider
.when("/a/:album_id", {
action: "album.list"
}).when("/i/:imgid", {
action: "images.load"
})
Then in your controller you can access $route.current.action and do the appropriate thing. The trick is to create a function in you controller that does all the work (the article calls it render()) and then call that function when $routeChangeSuccess fires:
$scope.$on(
"$routeChangeSuccess",
function( $currentRoute, $previousRoute ){
// Update the rendering.
render();
}
);
I created a super simple directive to handle this that allows routes to be have more like Rails or Codeigniter routes where the controller method is in the route definition. The method name is set in the routeProvider.when options and the directive is set in the template for the route.
See: https://stackoverflow.com/a/22714634/250991

Single Page website with CakePHP

I'm currently working on a single-page scrollable website (5 pages displaying as a single page) using CakePHP. I have worked on each controller action and everything runs well. I have one layout for the entire app and a view for each action. My challenge is finding a way to load the view of each action without reloading the page inside the layout. Should I just put all the view content inside the layout (without echoing $content_for_layout) or could there be a better way to do it?
Considering the div you want to update has the id #content:
$.ajax({
url:"http://yourdomain.com/controller/action",
context:document.body,
dataType:"html",
data:{id:123}, // in case you need to pass some params
success:function(data){
$("#content").html(data);
}
})
The action must return the HTML you want to display inside that div. If you want to have each pags loaded in different div's, you will have to create one div for each page and call AJAX for each one.
When the page is loaded for the first time, you can just pull the data for whatever default action you defined. Then, when you want to change the content, just call AJAX.

CakePHP - Render a view that is actually plugin's view from Component

Morning guys,
So this is my first time developing a plugin for CakePHP. Here's what I am doing in startUp of the component.
//component
function startUp(&$controller){
//....
if($render){
$controller->render("return", "ajax");
}
}
By default render will look at app/views/<controllers>/return.ctp and app/views/layouts/ajax for this render call.
Is there anyway that I can give a directive to render from app/my_plugin/views/awesome_stuffs/return.ctp and app/my_plugin/views/layout/ajax.ctp instead?
I believe the third param of Controller::render($file, $layout, $file) could do the job, but is there any better Cake way of doing things?
Plus, is that considered a good practice to take over controller's rendering function like that?
One way is to call the PLUGIN controller/action URL in your AJAX call, instead of the main app controller/action URL.
ex:
instead of:
http://domain.com/controller/action
you call:
http://domain.com/my_plugin/controller/action
When you do it this way, the plugin views & layouts are called automagically. See:
http://book.cakephp.org/view/1118/Plugin-Tips
http://book.cakephp.org/view/1115/Plugin-Views
Otherwise, the only way I know of is manually setting paths as you mentioned or controller-wide via:
var $viewPath = 'path/to/plugin/views/';
var $layoutPath = 'path/to/plugin/layouts/';
You might want to try setting $this->view to the plugin dotted view file you want to render.
add to your source
$controller->plugin = "pluginname";

CakePHP - How to have a modal layout

I am dynamically loading content into my modals, and often it will be a page that is already a normally accessible page on my site.
So I want to be able to reuse that controller/action and load it into my modal but obviously the controller already uses a layout. So when I load the page into my modal, the header and footer of my site is all in the modal again, which I don't want.
One solution I thought of that might work, but seems like a dirty workaround, is to have in my Appcontroller a check for a URL parameter that says it is a modal call for the page (not a regular call). It then overrides the layout with a special modal one.
//app_controller.php
public function beforeRender() {
if (isset($this->params['passed']['_modal'])) {
$this->layout = 'modal';
}
}
// In my jQuery call to open the modal:
myModal.load('users/view/5/_modal').dialog('open');
Then in the modal.ctp layout I would include a stylesheet that looks something like:
// modal_layout.css
#import url("normal_layout.css");
.header, .footer {display:none;}
So I don't have to redefine all of my normal layout's CSS but I can just hide the parts I don't want to show.
This seems like a bit of a stupid method of doing it, and I don't know if it even works, but surely someone has had to do this before with CakePHP, so what would you guys suggest?
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
}
Now you can configure your Layout/ajax.ctp as you want.
You could create an element.
$('#myModal').load("<?=url('users/view/5/_modal')?>", {type:'post'}, function(){
$('#myModal').dialog({title:'open',autoOpen:false, modal:false, height:600, width:700});
$('#myModal').dialog('open');
});
function view($my_customer_id, action) {
//do stuff here
$this->render(DS.'elements'.DS.'users'.DS.'modal');
}
use RequestHandler to detect ajax request. Put this line at the end of your action:
if ($this->RequestHandler->isAjax())$this->render('view_name','ajax');
It turned out I didn't need to anything so complex. I simply created a hidden div in my layout:
<div id="modal"></div>
And then in my layout's existing CSS I added certain rules to hide elements I don't want to see when a page is loaded in a modal:
#header, #footer {display:none;}
That way I can load a page into the modal but it still has all the normal styling that is already defined in the layout's CSS. Pages are loaded into the modal by using their normal CakePHP URL:
$('#modal').load('controller/action/param:whatever').dialog('open');
If you want the content of your modal dialog box to be simply the content of the view of an action you simply need to add the following a the top of the controller's action:
$this->layout = null;
This will disable the layout and all output the content{html} of the view

CakePHP dynamic element

I am trying to create a message-board type element in a CakePHP app. This element will be displayed on all pages and views that use a particular layout. I want it to display all the messages in the model, then show the add form when a link is clicked, then return to the updated message list when submitted. All this without affecting the current view/page.
I have my message model/controller/index set up, with a message board element that requests the index action. This works fine. However I am perplexed about how to return back to the original page/action from which the link was clicked. I can't use $this->referer() because that will link back to the add() action; what I want rather is to link to the page/view before that.
Any general pointers on how to achieve something like this?
I would approach this using Ajax, and use an ajax layout.
$this->layout('ajax')
Then you would be able to setup a full stack for processing this, and pass various things in as parameters into the controller actions.
By using Ajax you will not need to worry about passing in the referrer controller / action pair. You can also use the return from this to update the list by calling out to the MessagesController. The added bonus of this is that you can just switch the layout in your actual controllers, thus not having to write any extra code at all.
In your controller, you can check for Ajax
if($this->params['requested']){
$this->layout('ajax');
return $data;
}else{
$this->set('data',$data);
}

Resources