Simple ajax in laravel 4 - ajax

i have following code
ajax
//ajax edit button
$('.edit_button').on('click', function(e) {
e.preventDefault();
var id_produk = $(this).attr('id');
$.ajax({
type : "POST",
url : "editproduk",
data : id_produk,
dataType: 'JSON',
success : function(data) {
alert('Success');
console.log(data);
},
error: alert('Errors')
});
});
i always get messagebox error
and don't know where i'm missing,
because in chrome - inspect element - console not give any clue
my route
Route::post('/account/editproduk', array(
'as' => 'edit-produk-post',
'uses' => 'AccountController#postEditProduk'
));
my controller
public function postEditProduk() {
if (Request::ajax()) {
return "test test";
}
}
extended question
i running my script well after using return Response::json() like this
$id_produk = Input::get('id_produk');
$produk = Produk::findOrFail($id_produk);
return Response::json($produk);
and access it in view by this script
success : function(data) {
alert('Success');
console.log(data["name-produk"]);
}
but if i want to return array json like
$id_produk = Input::get('id_produk');
$produk = Produk::findOrFail($id_produk);
$spesifikasi = SpesifikasiProduk::where('id_produk', '=', $id_produk);
return Response::json(array($produk, $spesifikasi));
i can't access it in view like this...
success : function(data1, data2) {
alert('Success');
console.log(data1["name-produk"] - data2["title-spek"]);
}
how to access json array
extended question update
if i'm wrong please correct my script
because i get a litle confused with explenation
is this correct way to return it?
Response::json(array('myproduk' => 'Sproduk', 'data2' => 'testData2'));
result
console.log(produk["myproduk"]);
--------------------------------
Object {id_produk: 1, nama_produk: "produk1", deskripsi: "desc_produk"
console.log(produk["data2"]);
--------------------------------
testData2
and i still don't have idea how to print nama_produk in my_produkarray

Question 1:
Why is this code not sending JSON data back.
public function postEditProduk() {
if (Request::ajax()) {
return "test test";
}
}
Answer: Because this is not the right way to send the JSON data back.
From the Laravel 4 docs, the right way to send JSON data back is linked. Hence the correct code becomes:
public function postEditProduk() {
if (Request::ajax()) {
return Response::json("test test");
}
}
Question 2:
Why am I not able to access the data in data1 and data2
success : function(data1, data2) {
alert('Success');
console.log(data1["name-produk"] - data2["title-spek"]);
}
Answer: Because this is not the right way to catch the JSON data. The right way to send is given in the Laravel 4 API reference docs.
static JsonResponse json(string|array $data = array(), int $status = 200, array $headers = array(), int $options)
As you can see the method json takes string or array as the first parameter. So you need to send all your data in the first parameter itself (which you are doing). Since you passed only one parameter, you have to catch only 1 parameter in your javascript. You are catching 2 parameters.
Depending on what $produk and $spesifikasi is, your data will be present in one single array. Lets say that $produk is a string and $spesifikasi is an array. Then your data on the javascript side will be this:
[
[0] => 'value of $produk',
[1] => array [
[0] => 'value1',
[1] => 'value2'
]
]
It would be best if you print the log your entire data and know the structure. Change your code to this:
success : function(data) {
console.log(data.toString());
}
This will print your entire data and then you can see the structure of your data and access it accordingly. If you need help with printing the data on your console, google it, or just let me know.
I sincerely hope that I have explained your doubts clearly. Have a nice day.
Edit
extended question answer:
Replace this line:
$spesifikasi = SpesifikasiProduk::where('id_produk', '=', $id_produk);
With this:
$spesifikasi = SpesifikasiProduk::where('id_produk', '=', $id_produk)->get();
Without calling the get() method, laravel will not return any value.
Then access your data in javascript like this:
console.log(JSON.stringify(data));
This way you will get to know the structure of your data and you can access it like:
data[0]["some_key"]["some_other_key"];

In your controller you're returning text while your ajax request awaits json data, look at these lines of codes, I think you should get your answer:
if(Request::ajax()) {
$province = Input::get('selectedProvince');
//Get all cites for a province
if ($cityList = City::where('province_id','=', $province)) {
return Response::make($cityList->get(['id', 'name']));
}
return Response::json(array('success' => false), 400);
}

Related

How to correctly return html template from ajax request with Symfony

I was wondering how to return correctly an HTML template (SEO friendly) from an ajax call.
In my app, I use 2 differents ways to return response:
For simple template:
public function ajaxCallAction() {
//.....
$response = array(
"code" => 202,
"success" => true,
"simpleData" => $simpleData
);
return new JsonResponse($response);
}
And in the JS I do something like:
$("div#target").click(function(event) {
$.ajax({
type: "POST",
success: function(response) {
if(response.code === 202 && response.success) {
$("div#box").append(response.simpleData);
}
}
});
});
For complexe template (more than 20 lines and various var):
public function ajaxCallAction() {
//...
$listOfObjects = $repo->findAll();
$viewsDatas = [
'listOfObjects' => $listOfObjects,
//....other vars
];
return $this->render('myAppBundle:template:complexTemplate.html.twig', $viewsDatas);
//in complexTemplate.html.twig, I loop on listOfObjects for example...
}
And for this kind of call, the JS looks like:
$("div#target").click(function(event) {
$.ajax({
type: "POST",
success: function(response) {
$("div#box").append(response);
}
});
});
All those methods are working, but with the second one, we dont have status code (does it matter?) and I know that returning directly formated html template can be heavy (according to for example this topic Why is it a bad practice to return generated HTML instead of JSON? Or is it?).
How are you guys doing ajax calls? What are the best practices here?
In my apps, I typically use something like that:
$response = array(
"code" => 200,
"response" => $this->render('yourTemplate.html.twig')->getContent() );
Hope this help!
Edit
To return your response, you should use JsonResponseas explained in docs: http://symfony.com/doc/current/components/http_foundation.html#creating-a-json-response
Simply use that:
return new JsonResponse($response);
Try with "renderView" ;)
return $this->json([
'html' => $this->renderView('template.html.twig', []),
]);

Display result of search within view

I have a page where I display all my clients. It uses paginate and only displays 16 clients per page. As such I have provided realtime search functionality.
When a search is perform, the option selected from the results triggers the following
select: function (event, ui) {
$.ajax({
url: "/returnClient",
type: "GET",
datatype: "html",
data: {
value : ui.item.value
},
success: function(data) {
$('.container').fadeOut().html(data.html).fadeIn();
}
});
}
That essentially calls the following function
public function returnClient(Request $request)
{
if($request->ajax()){
$selectedClient = $request->input('value');
$client = Client::where('clientName', $selectedClient)->first();
$html = View::make('clients.search', $client)->render();
return Response::json(array('html' => $html));
}
}
If I output the client variable above, I can see all the details for this particular client. This is then being passed to the partial clients.search.
Within clients.search, if I do
{{dd($client)}}
I get Undefined variable: client. Why does it not get the parsed Object within the view?
Many thanks
The issue is that you are improperly passing $client to the view. The Views documentation shows how to properly pass data via an associative array. The API docs confirm that an array is what is expected.
Do this instead:
public function returnClient(Request $request)
{
if($request->ajax()){
$selectedClient = $request->input('value');
$client = Client::where('clientName', $selectedClient)->first();
$html = View::make('clients.search', ['client' => $client])->render();
return Response::json(array('html' => $html));
}
}
Also, as a point of habit you may want to consider using dump() instead of dd().

How to get data back from a $.post call?

I don't want to refresh a page when I am searching through a database eg. on post, so I had help in using a $.post call which works for sending information. There is a .done(function( data ){ line which I haven't used yet.
I also came across this question which I'm not sure if this ties to my question.
Return $.get data in a function using jQuery
I'm trying to search through a database, string match, and return the rows with matching strings. But I want to do this without refreshing the page so I would think that I am using the $.post call and using the .done(function( data ){ which is triggered by javascript (a button).
So I have two parts, the page I'm on and a separate PHP page that processes the call when made.
How do I make the bridge where I can return the data back? Or is there an easier way to do this?
The method .done(function(){}) is exactly what You would like to use, but You can also take a look at third argument (callback) of $.post function.
On server side, do all the queries and prepare the stuff in jsoned array like:
// set up data to send
$contentArray = [
'content' => 'Some content',
'foo' => 'bar',
];
$jsonResults = json_encode($contentArray);
// you can always send header('Content-Type: application/json'); instead of using simple die function.
die($jsonResults);
Then on client side:
<div class="content-container"></div>
<script type="text/javascript">
function someFunc() {
(...)
$.post(addr, values, function(res) {
var response = $.parseJSON(res);
$('.content-container').html(response.content);
});
}
</script>
This should update the content of the .content-container class only. You can send as much as you want, even prepared view to be displayed in the container. This is up to You.
EDIT:
Just to be sure, you're calling someFunc() on some button click event, right? If not, do it as follows:
<div class="content-container"></div>
Click here
<script type="text/javascript">
function changePageContent(addr, contentId) {
$.post(addr, {contentId:contentId}, function(res) {
var response = $.parseJSON(res);
$('.content-container').html(response.content);
});
}
$('.callMe').on('click', function() {
changePageContent($(this).attr('href'), $(this).attr('data-content-id'));
return false;
});
</script>
someScript.php:
<?php
// you should force your script to allow only XML HTTP request here
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
die('AJAX requests only..');
}
// always remember to escape somehow your post values before you use them
$contentId = is_numeric($_POST['contentId']) ? intval($_POST['contentId']) : null;
if (null == $contentId) (...) // throw exception or return status=false
// do your mysql query like: "SELECT * FROM content WHERE id=".$contentId;
// well, it would be better to send headers instead of that
die(json_encode([
'status' => true, // this is a good practice to send some info, if everything is fine, if mysql row has been found etc..
'result' => $result, // mysql row, this is just in case you need other values to display
'content' => $result['content'], // I assume you have 'content' column in your mysql
]));
?>
Take a look at the docs for Ajax, there really is a lot of info there which will help.
In short, you could do something like this:
function myPost() {
// Set the data
var data = {
'key' : 'value',
'key_2' : 'value_2'
};
// Do the post
$.post( '/your-url/', data, callBack );
}
function callBack( data ) {
// If the $.post was successful
success: function( data ) {
// do stuff
console.log( data ); // returned from your endpoint
},
// If there was an error
error: function( jqXHR, textStatus ) {
// do stuff
console.log( "Request failed: " + textStatus );
}
}
// On click of your element, fire the post request
$('#element').on('click', function() {
myPost();
});

Typeahead.js JSON response not rendering

I'm trying to integrate Twitter Typeahead into my Laravel (4.2.11) project (with Bootstrap 2.3.2).
I have results being returned as JSON (checked with Fiddler), but a single "undefined" is always displayed instead.
If I enter a search query that doesn't return any results, the "No Results" is displayed correctly.
//Simple query in Laravel
Route::get('/sidebar/clients/{q}', function($q)
{
$companies = DB::table('ViewCompanies')->select(array('CompanyID', 'FullCompanyName'))
->where('FullCompanyName', 'like', '%'. $q .'%')->get();
return Response::json(array('companies' => $companies));
});
//Javascript in page
var clients = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('FullCompayName'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/sidebar/clients/%QUERY',
filter: function (parsedResponse) {
// parsedResponse is the array returned from your backend
console.log(parsedResponse);
return parsedResponse;
}
}
});
clients.initialize();
$('#clients .typeahead').typeahead({
hint: true,
highlight: true,
minLength: 3,
},
{
name: 'clients',
valueKey: 'CompanyID',
displayKey: 'FullCompanyName',
source: clients.ttAdapter(),
templates: {
empty: [
'<div class="tt-empty-message">',
'No Results',
'</div>'
],
header: '<h3 class="tt-tag-heading tt-tag-heading2">Matched Companies</h3>'
}
});
My console log using the above code:
what is the output of the parsedResponse you are logging? I think DB::table returns an object, not an array. Try to replace the response like this:
return Response::json(array('companies' => $companies->toArray()));
Then log the results and format them in the "filter" function in the Bloodhound object.
Hope it helps!
Thanks to Eduardo for giving me the idea of needing to parse my JSON into a JS array.
Doing a search revealed these two questions:
Twitter Typeahead.js Bloodhound remote returns undefined
Converting JSON Object into Javascript array
from which I was able to devise my one-line solution (full remove filter show):
filter: function (parsedResponse) {
console.log(parsedResponse);
var parsedResponse = $.map(parsedResponse, function(el) { return el; });
return parsedResponse;
}

jQuery AJAX call, how to handle

I'm wondering what is the best method to handle AJAX calls with jQuery? Right now I'm doing something like following:
$("#test").live('click', function(){
// Process form
$.ajax({
type: "post",
url: "test.php",
success: function(html){
if(html.success == 0) {
alert('Error');
} else {
var obj = $.parseJSON(html.rows);
$("#success").html(obj[0].name);
}
},
dataType:'json'
});
return false;
});
In test.php file, I'm checking if request is an AJAX request. If it's an AJAX request I'm running a database query to get some data (this part isn't important in this question, I think):
// query goes here
if(mysql_num_rows($query) > 0 ) {
$result['success'] = 1;
$result['data'] = json_encode($data);
} else {
$result['success'] = 0;
}
Now I'm wondering if my method is the best possible? FYI I'm using KohanaPHP framework currently, so I want to not break MVC "rules". If I'm doing it wrong, do you have any tips and suggestions how to handle AJAX calls in controllers?
Regards,
Tom
What you have looks good here, though I don't think you need a $.parseJSON() there, it should already be an object at that point, this should work:
$("#success").html(html.rows[0].name);
As a side note, from a readability/maintainability perspective, I'd rename your html argument to be data, like this:
success: function(data) {
This is purely preference, but using html when it's an HTML type response, and data or something else when it's JSON/already an object you're expecting keeps things a bit easier to read for outsiders.
#tom - you need to encode the PHP array like this:
$data = array(
'status' => 'success'
);
echo json_encode($data);
But you might want to change the array structure a little. Since the xhr object has a text status I usually encode an JSON array like this:
$response = array(
'status' => 'success' // or flash or error
,'flash' => array(
'header' => 'whatever is wrong with submission of data html list format'
'fields' => array('field names to be highlighted')
)
,'html' => 'html presentation'
,'data => array('json data')
);
echo json_encode($response);
Now you can do some nice things like this:
,success: function(response) {
if (response.status === 'success') {
$('.basic_container').hide();
that.removeDataTable();
that.getContent(contentUrl);
$('.basic_container').show();
}
if (response.status === 'flash') {
$('#flash').html(response.flash.header);
$('#flash').show();
that.highlightWithFlash(response.flash.fields);
}
}

Resources