CakePHP AJAX Layout
I'm working with a CakePHP application and jQuery Mobile. In the CakePHP application, RequestHandler is turned on, now, jQuery Mobile makes all of it's requests as ajax requests but requires a full page not 开发者_如何学JAVAjust what is in my view but the full layout to.
I need requesthandler and I've tried to set a layout, force a render, turn off autolayout, nothing works, cake only returns the contents of my view.
I'd really love to know what's going on here.
If anyone is interested I found a solution to this, I found out that when you have RequestHandler on and make a Ajax request, it doesn't matter what you do, RequestHandler then decides that your layout is 'ajax' via call backs, this probably applies for all non-html request types, like json and text.
I had to set
$this->RequestHandler->enabled = false;
It really needs to be set in beforeFilter() as well, latter in the call chain and it appears to not work.
So my code ended up as:
class AppController extends Controller {
var $components = array('RequestHandler');
function beforeFilter() {
if ($this->RequestHandler->isMobile()) {
$this->RequestHandler->enabled = false
//set special mobile rules here
}
}
}
I was having the same problem with a CakePHP 1.3 app that is using jQueryMobile to build mobile-friendly views. I'll try to lay it out for future searches.
When I switched on $.mobile.ajaxEnabled = true;
for jQM's nice Ajax-based navigation all the linked pages showed undefined
instead of the page content. The Ajax nav requires that the linked page have the proper structure, like so:
<div data-role="page">
<div data-role="header">
<h1>Page Title</h1>
</div><!-- /header -->
<div data-role="content">
<p>Page content goes here.</p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div><!-- /page -->
This markup was coming from two places for my app, though: my default mobile layout had the <html>
, <body>
and the page
and footer
divs. Each view had a header
and content
div.
The problem arose because Cake's RequestHandler wanted to set the layout to ajax
for all Ajax requests. It does this somewhere after beforeFilter()
, which caused it to ignore a declared layout there (which Luke mentions).
The ajax
layout is empty, unlike my default layout--it doesn't have <html>
and other markup because it assumes (rightly) that you only want partial markup that will be inserted into a page by Ajax. The jQuery Ajax-based navigation does want to see the full markup though, and when it didn't receive a well-formed page when making the Ajax request it had no page to display.
So the question became, "How do I make RequestHandler use my default mobile layout for mobile page requests?" I wasn't satisfied with Luke's solution above of disabling RequestHandler completely for mobile. Luckily I found a post from May '11 with the same problem and a better solution:
Finally sorted it! I was checking to see whether a mobile device was requesting the page using $this->RequestHandler->isMobile(), but had placed it in the beforeFilter() function. Moving this to the beforeRender() function in the app_controller.php file fixed the problem. http://cakephp.1045679.n5.nabble.com/Jquery-Mobile-and-CakePHP-1-3-td4422871.html
So my code ended up something like this in AppController:
function beforeRender() {
if ($this->RequestHandler->isMobile()) {
$this->layout = 'm_default';
}
}
I hope that helps someone out there.
Just set $this->layout = 'default';
in your controller, and it will use the default layout.
Or maybe you could make a header and footer element to put in your ajax and default layouts.
I was new to CakePHP and started with Version 2 several weeks ago.
So far I also keep the beforeFilter untouched to identifier isMobile()
and finally use mobile-views within a Themed-Folder. Therefore I dont use subfolders for mobile-views within the default desktop-views. After adding this->layout in the condition it seems that I got rid off the undefined
which appeared only via some actions links.
public function beforeRender() {
if($this->RequestHandler->isMobile()) {
$this->theme = 'Mobile';
$this->layout = 'default';
}
}
The best sollution I think is to configure the request handler in before filter after the mobile browser was detected in your app controller:
public function beforeRender() {
if($this->RequestHandler->isMobile()) {
$this->theme = 'Mobile';//set your theme
$this->RequestHandler->ajaxLayout = 'public';//this does the trick, set your mobile layout, $this->layout is simply ignored or overwritten by the component
}
}
精彩评论