Check to see if a page is called via Ajax in Laravel - ajax

This is an extension from a post I made a few days ago: Change a page without refreshing - Laravel / Ajax
Basically, I'm trying to replicate the URL Structure of Soundcloud where you can click on a link, it'll load the content without refreshing the page however if you land directly on that page, it won't replicate design and effecitvely break.
I've been thinking of ways on how I can check in Laravel if the page is requested via Ajax or has been landed on without an Ajax call.
What's happening at the moment is that when I call the page, the view has a master template that's extended thus creating duplicate master templates on the one view.
I was thinking if I done something like
#if(!Request::ajax())
#extends('masterlayout')
#endif
It would work but tried and no luck.
Any help as always is greatly appreciated!
Thanks

Looks like #extends directive is always executed even in falsy if
You can add an empty layout and perform check like this:
#extends(Request::ajax()? 'layouts.empty' : 'layouts.master')
and you need add only this in layout empty.blade.php:
#yield('content')
or you can add ajax check in the master layout
#if(!Request::ajax())
// all layout code
#else
#yield('content')
#endif

You can check that in your controller action.
public function index(Request $request)
{
if($request->ajax()){
return "This is an AJAX call!";
}
return "Not an AJAX call...";
}

Thanks for all the answers, I eventually got this fixed by using #if(!Request::ajax()) on section that didn't need to be shown when the page was loaded via ajax.
Thank you again! :D

Related

Laravel Redirect as POST

Currently my users must get the visit form given by Route::get then fill it in to get back a result view given by Route::post. I need to create a shareable link such as /account/search/vrm/{vrm} where {vrm} is the VRM that is usually filled in on the form page. This VRM then needs to redirected to Route::post as post data. This needs to be done by my controller. How can I do this in my controller?
Routes:
// Shows form view
Route::get('/account/search', 'User\AccountController#getSearch')->name('account.search');
// Shows result view
Route::post('/account/search', 'User\AccountController#runSearch');
// Redirect to /account/search as POST
Route::get('/account/search/vrm/{vrm}', function($vrm) { ???????? });
POSTs cannot be redirected.
Your best bet is to have them land on a page that contains a form with <input type="hidden"> fields and some JavaScript that immediately re-submits it to the desired destination.
You can redirect to a controller action or call the controller directly, see the answer here:
In summary, setting the request method in the controller, or calling a controller's action.
Ps: I don't want to repeat the same thing.
For those who comes later:
If you are using blade templating engine for the views, you can add '#csrf' blade directive after the form starting tag to prevent this. This is done by laravel to prevent cross site reference attacks. By adding this directive, you can get around this.
return redirect()->route('YOUR_ROUTE',['PARAM'=>'VARIABLE'])

Clarification needed in using Ajax forms and Partial Page

I am newbie to MVC and Web App.
Recently I have went through the article
http://www.c-sharpcorner.com/UploadFile/pmfawas/Asp-Net-mvc-how-to-post-a-collection/
It uses the Ajax Form, to do the partial update towards a particular region alone..
But I have a doubt in that example...
I have seen the partial Page inside the Div with Id "AllTweets"....
<div id="AllTweets">
#Html.Partial("_AllTweets", Model) ***** (XXX)
</div>
And also in the controller action,
try
{
viewModel.Tweets.Add(viewModel.Tweet);
return PartialView("_AllTweets", viewModel); **** (YYYYY)
}
Now my question is,
They are returning the partial view along with the data from the action in the controller.
Whatever the data returned from the controller, the engine will place that data, inside the target div with id "AllTweets"...
But still, why I have to have the statement, #Html.Partial("_AllTweets", Model) inside the Div, since already I am returning the data from the controller...
And also in some of the examples, i have seen the same kind of the code..
But, even if I have removed the code "#Html.Partial("_AllTweets", Model)" inside the div, the code still works fine, and without any problem and i can able to post the data to the action in the controller.
I got totally stuck at this point.
May I kindly know, what is the reason behind it and why so.... So I can understand it more better.
Thanks in advance...
But, even if I have removed the code #Html.Partial("_AllTweets",
Model) inside the div, the code still works fine, and without any
problem and i can able to post the data to the action in the
controller.
Yes it will work fine. The Html.Partial("_AllTweets",Model) renders the partial with the specified model on every page load. After page is loaded, then ajax is used to fill the div with id AllTweets.
Html.Partial("_AllTweets",Model) is usefull when you want to display, for example, already saved tweets from your database to user when the page first loads. And then ajax takes care of later updates.

Laravel usage "#layout" in Ajax Requests

Hi there stackoverflow!
In my laravel views I am using a default layout by calling
#layout('layouts.default')
to the same controller I am sending Ajax Requests yet I can't put 'if' to #layout if its a ajax call. Because if ajax request has made to controller it also produce header, footer and content(header and footer are in default layout). So to avoid this I made one copy without #layout of my view.
However its so boring to edit two files for making changes. Can't I add a code to my view something like that?:
#if(!$ajaxrequest)
#layout('layouts.master')
#endif
I want this because my codes in controllers are too messy
A slight variation is to put the logic for the layouts in your main layout template. e.g.
layouts/app.blade.php:
#if (Request::ajax())
#include('layouts.ajax-app')
#else
#include('layouts.default-app')
#endif
Your views just extend the main layout as usual e.g.
#extends('layouts.app')
#section('content')
Content goes here...
#endsection
And then create a default layout file (default-app.blade.php) and an ajax layout file (ajax-app.blade.php). The advantage of doing it this way is that any of your blade templates can be loaded via Ajax, without having to clutter up controller methods with lots of duplicated logic.
You can't have the #layout call after the if statement like that (see the notice in red under "Blade Templating" in the docs. You'll have to set the public $layout and call $this->layout->nest instead of View::make (see "The Basics" on the page linked to above).
You can use something like this in your view template:
#extends( 'layouts.' . (isset($layout) ? $layout : 'default'))
Also apply check in your controller(or Supercontroller) for AJAX request, if it is set $layout variable to needed layout. Otherwise "default" layout will be taken.

yii Ajax link not working

I put a Ajax link using the following code:
echo chtml::ajaxLink('GO', 'http://localhost/index.php?r=user/delete', array('method'=>'POST'));
But, regardless of giving the second parameter as URL i,e 'http://localhost/index.php?r=user/delete'. It generates link with the current URL in the browser not the URL I just specified.
What is the issue? How could I create AJAX link? Google several hours but can't solve the issue.
Any kind of help is highly appreciated.
First of all, you should always try and create normalized urls.
But i think your doubt lies in the # that is generated/appended. If you go and check the source of yii ajaxLink you'll see this:
public static function ajaxLink($text,$url,$ajaxOptions=array(),$htmlOptions=array())
{
if(!isset($htmlOptions['href']))
$htmlOptions['href']='#';
$ajaxOptions['url']=$url;
$htmlOptions['ajax']=$ajaxOptions;
self::clientChange('click',$htmlOptions);
return self::tag('a',$htmlOptions,$text);
}
so if you don't set the href property of the a tag in the htmloptions array, the # will be appended.
You should also understand that yii uses jquery, so if you check out the source of the page, you'll see at the bottom, how jquery is used to carry out an ajax request, your actual url that is called will also be seen in that script. So the third option/parameter in ajaxLink is for options for jquery's ajax function. You can create better ajax links using this option.
Regardless of where(which controller) your url points to in your project, the action associated with that url will be called.
So anyway, you can modify your code like this if you want the url to be shown and not a # :
echo CHtml::ajaxLink('GO', 'http://localhost/index.php?r=user/delete',
array('type'=>POST), //there are various other options for jquery ajax
array('href'=>'http://localhost/index.php?r=user/delete'));
To make better ajax links i would suggest going through jquery's ajax documentation. There is an option for a success function, that you can use to let the user know that the operation was completed.
Hope this helps, don't hesitate to leave comments if i haven't answered your question completely.
Have you tried:
echo CHtml::ajaxLink('GO', array('/user/delete'), array('method'=>'POST'));
as the ajaxLink documentation suggests...? Look also at the normalizeUrl method.
Using these methods, which in turn are using createUrl, is usually better since it will take care to create a valid url for your site.
I had the same issue(or maybe similar).
I've used renderPartial to load view and later in that view i was using ajaxLink and it was not working.
What i have found, that when using renderPartial, there was no jquery script for ajax action.
What you have to do is to add 4th argument(true) in renderPartial function to generate jquery script.
See the documentation: http://www.yiiframework.com/doc/api/1.1/CController/#renderPartial-detail
Hope it helps and saves time to figure it out.

RedirectToAction MVC 3 after $.ajax call

From my view I am sending via $.ajax a JSON object to my controller to save it in the database.
If all succeeded i want to redirect to another action which will show a diferent view.
If i use this code:
return RedirectToAction("CreatePage", "Survey", new {id = question.PageId});
The execution goes to the Survey controller which returns a view but it is not shown.
I have read some post which said that it is not posible to redirect via ajax.
The solution I use so far is to redirect via javascript like this:
success: function (ret) {
window.location.href = "/Survey/CreatePage/" + $("#PageId").val();
}
Although this always works, sometimes i need to refresh the CreatePage view to show the last changes made.
Any idea of how to solve this problem better?
Thanks in advance
As mccow002 suggested, I wasn't really needing to make the call via AJAX for that part. After studying the solutions suggested, i realized that i could simple submit it in a form. My confusion came because I have a save and continue editing and a save. For the save and continue I use the AJAX call, but for the save option with the form being submitted is ok.
Thanks very much for your help.
Instead of redirecting to a new page, you can send a rendered html from .net code back to client and load that html in page, like this $("#main").load(renderedHtml).
But for refreshing the page you can write a simple script that run at specified intervals and refresh the page contens.
You could use [OutputCache] on the CreatePage action so that it doesn't cache the page or only caches for so long.
output caching

Resources