I have integrated jQuery into a Spring MVC application. I have a form on my JSP page and I am doing an ajax POST to send the form to the controller:
$("#myform").submit(function() {
$.ajax({
type : 'POST',
url : '/MyApp/search/searchResults',
data : $(this).serialize(),
dataType: 'html',
success : function(data) {
$("#tabs-4").append(data);
}
});
return false;
});
The success function will load the data into a new tab. What I am finding is that data returns the HTML of my original page (from which I submitted). Instead, I would like to be able to parse the ModelAndView object that is being returned from the controller. For example:
${searchResults.searchStr}
Is it normal for data to return the page HTML? Is there anyway that I can parse the ModelAndView object in the success function, and then pass it to my new tab div?
Here is my Controller code:
#RequestMapping(value = "/searchResults", method = RequestMethod.POST)
public ModelAndView searchResults(
#ModelAttribute(value = "search") SearchVO search,
BindingResult result) {
// Set the view and search object
ModelAndView mv = new ModelAndView("newSearch");
mv.addObject("searchResults", searchResults);
return mv;
}
Thanks!
Yes you can return the html content from the controller to your ajax function. If you are interested in to use the instance in the jsp you would have to serialize it in to json and send it. Using jquery you could render it on the jsp. For example,
//Controller
public #ResponseBody<Class_name> search(...){
return searchResults;
}
//jsp
function renderResult(){
$.ajax({
url:'url',
dataType:'json',
...
..
success: function(data, status, xhr){
$.each(data, function(k, v){
$('#my_div').append(...k,v...);
}
}
});
}
Looking at your requirement I would suggest you to use the first method where you return the html itself and the jsp page which you return could be render with the searchResults.
Related
I am working on a bookstore project where books can be added to cart, a user can select many books for adding them to cart. when the user clicks on the Add to Cart button, I am adding the IDs of the selected books in a JS array called cart. When all the selected books are added to the cart then I want to link <a> tag with ajax call that will hit the url of a controller function and will send the JS cart array object to the controller function and then in the controller function, I want to return view to the browser, I do not want the controller function to return the response back to the ajax call but instead I want to return the view to the browser.
Here is the JS function that adds the ID of the selected books to the cart JS array:
function addToCart(id)
{
if(! cart.includes(id) ) cart.push(id);
cartLength.html(cart.length);
$('#successCart'+id).html('Book added to cart.');
}
Here is the <a> tag that calls the ajax function, the function name is showCart():
<a href="#" onclick="event.preventDefault(); showCart();">
<i class="fa fa-shopping-cart"></i>
<span id="cartLength"></span>
</a>
Here is the showCart() function that has ajax code:
function showCart()
{
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url:"cart",
method:'post',
data:{cart:cart},
dataType: 'html'
})
.done(function(msg){
});
.fail(function(msg){
alert(msg.responseJSON.errors);
});
}
Here is the controller function - I want this function to directly return the view to the browser without sending it back to the ajax call:
public function showCart(Request $request)
{
return view('cart', ['cart' => $request->cart ]); // this should be returned to the browser and not to the ajax call
}
Here is the route for the controller function:
Route::post('/cart', 'HomeController#showCart')->name('home.cart');
EDIT:
I have temporarily solved the issue with the following tricks but that is not a permanent solution:
After calling the showCart() function from ajax for sending the cart array variable from js to laravel controller, I used the following logic to store the books in a session variable whose ids are stored in the cart array:
public function showCart(Request $request)
{
session()->put('cart_books', Book::whereIn('id', $request->cart)->get());
session()->save();
return "success";
}
After storing the result of the query in a session variable, I created another GET route for /cart as below:
Route::get('/cart', 'HomeController#viewCart');
Then upon success of the post ajax call, I called /cart with get method as below:
.done(function(msg){
console.log('calling cart');
location.href = "cart"; // Here I call the `/cart` with `get` method which will hit the `viewCart()` function of HomeController which will return the view back to the browser along with the results that were stored in the session variable.
})
And this is the viewCart() controller function that returns the view to the browser and sends the session variable's data to the view:
public function viewCart()
{
$random_books = Book::all()->random(4);
$categories = Category::all();
return view('cart', ['cart_books' => session()->get('cart_books'),
'random_books' => $random_books, 'categories' => $categories]);
}
I want the controller function to return the view to the browser without returning it to the ajax call, any help is appreciated in advance.
You can return Raw html from ajax call by rendering and returning the view inside your controller as,
return view('cart', ['cart' => $request->cart])->render();
This will return the raw HTML and you can further use it. However, returning HTML from ajax is not a good way, You can return JSON from the controller and render the view in frontend according to the JSON data.
As the others said you can use
return view('cart', ['cart' => $request->cart])->render();
and in you jQuery do
.done(function(response){
document.write(response);
});
Or you can return the link that its content should be shown to the user and redirect the user in your done method. So in your back-end you'll have
return route('cart', ['cart' => $request->cart]);
and in your front-end you'll have
.done(function(response){
location.href = response;
});
In the controller function just add render method like the following line
public function showCart(Request $request)
{
return view('cart', ['cart' => $request->cart ])->render();
}
For js:
$.ajax({
method: 'POST', // Type of response and matches what we said in the route
url: '{{ route('home.cart') }}', // This is the url we gave in the route
data: {'cart' : cart}, // <-- this is your POST data
success: function(response){ // What to do if we succeed
console.log(response);
},
error: function(jqXHR, textStatus, errorThrown) { // What to do if we fail
console.log(JSON.stringify(jqXHR));
console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
}
});
You're doing a XHR, so you shouldn't return the whole HTML view from your controller unless you plan to replace your existing element with the returned HTML, like how you're doing with addToCart. What you need here is a redirection after your POST, and your temporary solution isn't actually a bad solution :) Here's a similar question as yours with the same answer. In fact, I highly recommend your temporary solution over the alternative solution below.
Since you wish to use the view returned from your controller without returning it to your ajax, a rather unorthodox approach would be to POST through a <form>. You can dynamically create a <form>, with the <input>s of your data, and submit.
function postData(actionUrl, method, data) {
var mapForm = $('<form id="mapform" action="' + actionUrl + '" method="' + method.toLowerCase() + '"></form>');
for (var key in data) {
if (data.hasOwnProperty(key)) {
mapForm.append('<input type="hidden" name="' + key + '" id="' + key + '" value="' + data[key] + '" />');
}
}
$('body').append(mapForm);
mapForm.submit();
}
function showCart()
{
postData('cart', 'post', cart);
}
I borrowed the above code from here. You can do the same with vanilla JS too.
Hi I am new to Laravel having a situation like: I have a HTML form and loading some HTML like "partial.blade.php" using AJAX in Same form, that is working perfectly with static HTML but,
I want to send a JS Array of object with AJAX Request to Dynamically loading HTML Content like: Drop down in same form
Could any Guide me how Can i Pass JS Array to that piece of HTML so i can Render that Array in "partial.blade.php"
here is my code
this is main form HTML & Array i want to pass with this AJAX Request
var dataArray = $('#data1').val();
code included at last in HTML Form Page
$.ajax({
url: "add-property/residential",
type: 'GET',
dataType: 'html',
data: { dataArr: dataArray },
contentType: false,
processData: false,
success: function(response) {
console.log(response);
$('#dynamicForm').html(response);
//alert(response);
},
error: function(response) {
console.log(response);
alert('Error....!');
}
});
here is my Route
Route::any('admin/add-property/residential',function() { return view('admin.residential'); });
all i want to receive that JS array in this piece of HTML that is dynamically loading
When you want to return the contents of a view() to an AJAX request, you can store the view as a variable and return in a JSON response:
public function apiResponse(){
$html = view("admin.residential")->render();
return response()->json(["html" => $html]);
}
In your AJAX request, you can access this as response.html:
success: function(response) {
$("#dynamicForm").html(response.html);
}
To pass a variable from AJAX to the view, you can use the request object. At the top of your routes/api (or routes/web.php, whichever you're using) add use Illuminate\Http\Request;, then in your Route inject that into the function:
<?php
use Illuminate\Http\Request;
...
Route::any('admin/add-property/residential',function(Request $request){
...
});
Not that $request is available, you can access the data being sent in the AJAX request via $request->input("dataArr");, and pass that to the view partial using ->with();:
Route::any('admin/add-property/residential',function(Request $request){
$dataArr = $request->input("dataArr");
$html = view("admin.residential")->with(["dataArr" => $dataArr])->render();
return response()->json(["html" => $html]);
});
According to this
Instead of return view('admin.residential');
You need to do this: return (string) View::make('admin.residential');
Edit
If you want to receive data from the ajax, and then load the view, you could do something like this:
Import the Request.
use Illuminate\Support\Facades\Response;
Make your rote point to a specific method on a controller.
Route::any('admin/add-property/residential',"YourController#returnView");
Make your function to handle the data
public function returnView(Request $request){
$data = $request->all(); // Here you will have all the data you send via AJ
//Make sure the $data has all the necessary parameter to load the view
$view = View::make('my_view', $data);//Here you will pass the data to the view
return response()->json(["html" => $$view->render()]); // Using #TimLewis return
}
I have a javascript function that sends to a Controller some information (mostly vars like arrays and ids) to be inserted in a table, the problem is after the insertion is completed I want to return to a different view with a data array and i cant seem to do this (I think its because of the ajax request)
Javascript Code
$('#importar').submit(function(e) {
e.preventDefault();
fdata=preparePostData();
$.ajax({
type:'POST',
url: $(this).prop('action'), // url, from form
data:fdata,
processData: false,
contentType: false,
success:function(data) {
window.location.replace(data.url);
}
});
}); // end form.submit
Function Prepare PostData()
var file_data=$('input:file')[0].files;
var postdata=new FormData();
postdata.append('_token',token);
postdata.append('startFrom',startFrom);
postdata.append('idList',idList);
postdata.append('nomeCampos',nomeCampos);
postdata.append('posicaoCampos',posicaoCampos);
postdata.append('file',file_data[0]);
return postdata;
Controller Expected Code
Do all inserts and functions and in the end
$data = array('listNome' => $listName, 'contacts' => $contacts, 'errors' => $erro);
return view("XPTO", $data);
You should not return a view from an ajax call, because you'd get the view processed code as a parameter to the ajax callback. Think of an ajax call as an async 'behind the scenes' call to the server in which you pass parameters and get some other parameters back
You should instead return a JSON response from the controller with all the parameters you'll need to call the route from JS, and parse it in your success callback. For example:
Controller
//here you should store all the parameters you need in your JS calback
$data = array('status' => 'ok', 'url' => $redirect_url );
JS
success:function(data)
{
//data will contain the parameters you set in the controller, so you can use them to call the route
if ( data.status == 'ok' )
window.location.replace(data.url);
}
Just elaborating previous answer , Ajax call controllers are used to supply some data behind the scenes and standard controllers are used to control the view so best practise is to return data (JSON) form Ajax controller to the same view which requested the data. while the standard controller should be used to control the views.
SOLVED
Not the most elegant solution but what I did was set the array with errors as an session variable and get that session var in the specific controller I need.
Controller
$request->session()->put('importErrors',$erro);
$response = array('status' =>'success','url' => '/ListarContactos/'.$idList);
return response()->json($response);
JavaScript
$('#importar').submit(function(e) {
e.preventDefault();
fdata=preparePostData();
$.ajax({
type:'POST',
url: $(this).prop('action'), // url, from form
data:fdata,
processData: false,
contentType: false,
success:function(data) {
if(data.status=='success'){
window.location.replace(data.url);
}
}
});
}); // end form.submit
XPTOController
$errorArray= $request->session()->get('importErrors');
After using it you can destroy the session variable or keep it(depending if you need it or not).
I am new to Spring with AJAX.
My requirement is to check whether email is registered or not, when user clicks on check availability. I am successfully making calls to the controller class but the response is displayed in the browser instead of in same jsp and not entering the success block. I am unable to find the problem.
Below is sample code:
#Controller
public class CheckAvailbiltyEmailController {
#RequestMapping(value="/check",method = RequestMethod.GET)
public ModelAndView viewAjaxEmail(Map model){
return new ModelAndView("CheckEmailAvaliblity");
}
#RequestMapping(value="/check", method=RequestMethod.POST)
public #ResponseBody String ajaxEmailCheck(#RequestParam("email") String email){
System.out.println("Email is:"+email);
return "Please carry on registration";
}
}
My Ajax code:
$.ajax({
type:"POST",
url:"/check"
success:function(data){
alert("Inside Success");
$('#resp email').html(data);
}
error: function(e){
}
});
You need to specify the data you want to send to the server,
The controller will accept "email" as the RequestParam.
Do it like the following snippet :
$.ajax({
type:"POST",
url:"/check",
data: {"email":"email#to.check.com"},
success:function(responseData){
alert("Inside Success");
$('#resp email').html(responseData);
},
error: function(e){
}
});
I am new to Ajax. i am trying to call my controller method but call from Ajax not invoking url i am given.. here my controller method and ajax call in my jsp file..
#RequestMapping(value = "/getdata", method = RequestMethod.POST)
public #ResponseBody String add(#RequestParam(value="userDetailObject", required=true) User_Details u,Model model) {
System.out.println("In the controller method..");
String result=null;
result="From controller :"+u.getEmail();
System.out.println("at controller .."+result);
return result;
}
and my Ajax is
//script type="text/javascript" src="../jquery-1.4.4.js"
var jq = jQuery.noConflict();
function getData() {
alert("hello");
// get the form values
var email = $('#email').val();
// var education = $('#education').val();
$.ajax({
type : 'POST',
dataType: 'json',
url : "/SpringDemoSts/getdata",
data : 'email=' + email,
success : function(response) {
// we have the response
//$('#info').html(response);
$('#email').val(response);
//$('#education').val('');
},
error : function(e) {
alert('Error: ' + e);
}
});
}
/script
what is wrong i am doing wrong here ?
the url defined in ajax :
/SpringDemoSts/getdata
is didfferent to that in the requestmapping shown
/getdata
and the parameter is called userDetailObject and your ajax call defines data incorrectly,you are using request parameters style as the data. When in fact you need json/a plain primitive or string.