laravel array of strings to route action - ajax

A javascript code uses "map" method on array of object to extract just the text value:
var checked_leaves = checked_ids.filter(function(elm) {
if (elm.children.length == 0)
return elm;
}).map(function(elm, index) {
return elm.text.trim();
});
this array of string is sent to a Laravel route using ajax (with Vue http)
this.vm.$http.get(this.el.action + checked_leaves).then((response) => {
console.log(response);
//this.vm.speciesDetails = JSON.parse(response.data);
}, (response) => {
});
Where the this.el.action is api/taxonomytospecies/ and the corresponding Route is:
Route::get('api/taxonomytospecies/{ids}', 'TaxonomyController#getSpeciesFromTaxonomy');
And inside TaxonomyController:
public function getSpeciesFromTaxonomy($ids) {
// Eloquent job to retrieve the data from the DB
}
1) Is there a better way to pass an array of values like the one I get from the javascript code (they are a lot of strings) to a route of a controller?
2) I get an internal 500 error. The error shows that the call is like :
api/taxonomytospecies/name1,name2,name3,name4,name5
But i don't know how to resolve this kind of error

I would suggest you to use post request instead of get as the data is large.
You can send data as an array to the server.
var data = {ids: checked_leaves};
Then send data variable in your post request.
In your controller you can get data as:
public function getSpeciesFromTaxonomy() {
$ids = request()->get('ids') // returns an array.
// Eloquent job to retrieve the data from the DB
}
And your route should be as:
Route::post('api/taxonomytospecies', 'TaxonomyController#getSpeciesFromTaxonomy');

The solution is to set the Route as:
Route::get('api/taxonomytospecies/', 'TaxonomyController#getSpeciesFromTaxonomy');
And the Vue-resource request as:
this.vm.$http.get(this.el.action, {params: { ids: checked_leaves } }).then((response) => {
but i don't understand why.

Related

Laravel 5.4 controller function not able to use a get request parameter from ionic 3

I am try to pass a from ionic application to a laravel 5.4 application, and this parameter is an array, i have been able to pass the parameter successfully but i am being able to use the parameter to select records from the database.
Here is my ionic 3 provider function:
getMySmartQueues(data){
let params = new HttpParams();
params = params.append("sq_ids", JSON.stringify(data));
return this.http.get(this.url + 'my/smart/queues', {params: params});
}
And here is my laravel controller function:
public function getMySmartQueues(Request $request){
$ids = $request['sq_ids'];
$my_sq = SmartQueue::whereIn('id', $ids)->get();
return $my_sq;
}
And here is how i subcribe to the provider function is my page:
ionViewDidLoad() {
this.storage.get('sq_ids').then(
res => {
console.log(res);
if(res != null){
this.sq_ids= res;
console.log(this.sq_ids);
this.mService.getMySmartQueues(this.sq_ids).subscribe(
data => {
console.log(data);
}
);
}
}
);
}
But i get Server internal error. But if i have to hard code a default value for the controller function, let say like [5,6], it will return the records of this ids, but it can not returns the records of the ids sent from the ionic 3 application, will be glad if any one can help me out.
Also if i change the request to a put request i can get the records of the ids sent from the ionic application. But a get request is what i want.
if you want to use controller function with GET you need allow arguments in the Route to allow your id array.
for an example.
Route::get('your/url/{ids}', 'Controller#function')->name('mane_of_the_route');
and the controller function
public function getMySmartQueues(array $ids){
$my_sq = SmartQueue::whereIn('id', $ids)->get();
return $my_sq;
}
I have figure it out, and this is what i had to do, i think it might help someone one day, i just had to json_decode the request like so:
public function getMySmartQueues(Request $request){
$ids = $request['sq_ids'];
$my_sq = SmartQueue::whereIn('id', json_decode($ids))
->with(
'station.company'
)->get();
return $my_sq;
}

Laravel Eloquent Resource Collection response

So I am trying to use a resource collection to return datatable json information. Before I used my collection I first did a proof of concept that looked like this:
public function index()
{
$clients = QueryBuilder::for(Client::class)
->allowedIncludes('accounts')
->get();
if (request()->ajax()) {
return DataTables::of($clients)->make(true);
}
return view('client.index', compact('clients'));
}
This worked perfectly and the json response looked like so:
{data: [{id: "4428", number: "492501", name: "Test Client", email: "test#test.com",…},…]
draw:1
input:{view: "datatable", draw: "1",…}
recordsFiltered:2
recordsTotal:2}
Then I updated my index call to use my resource collection that looks like this:
public function toArray($request)
{
switch ($request->view) {
case 'datatable':
self::withoutWrapping();
return DataTables::of($this->collection)->make(true);
}
return parent::toArray($request);
}
The response is now plopped in an "original" attribute and a bunch of other items are added to the response. I don't understand why. It looks like this:
*callback: null
*charset: null
*content: <The above response is in here as a string>
*encodingOptions: 0
*statusCode: 200
*statusText: "OK"
*version: "1.0"
exception: null
headers: {}
original: <The above response is in here as an object>
I can set my dataSrc on datatables to original.data and it works fine but where did all this extra stuff come from? I have used a few other resource collections and never had all this stuff added in.
Update: because everything i am looking for is in "original" the pagination breaks as well as most of the other datatable functionality. If I move this return back into the controller it works fine.
So, the answer has to do with response type. The eloquent resource has an undocumented function called "toResponse" and if your return is going to be some kind of jsonResponse you need to modify it instead of your toArray method. What was happening was I was returning a JsonResponse and it was turning it into an array and just returning that json encoded.
To be clear as mud, here is my new Resource:
public function toResponse($request)
{
switch ($request->view) {
case 'datatable':
self::withoutWrapping();
return DataTables::of($this->collection)->toJson();
}
return parent::toResponse($request);
}
So, to reiterate, if you are returning an array or something that conforms to an array correctly (which datatables jsonresponse does not) you override "toArray". If you are returning a jsonResponse you need to override "toResponse".
Another option is to have your code start in toArray but when you know your going to return a jsonResponse you call $this->toResponse($request). Option is yours.

Delete Method in Axios, Laravel and VueJS

I am trying to send a delete request via axios to laravel as follow:
axios.delete('api/users/' + this.checkedNames)
.then((response) => {
console.log(response)
}, (error) => {
// error callback
})
Now from axios documentation I read that for delete request we should be using a configObject so the above could be rewritten as so:
axios.delete('api/users/', {params: {ids:
this.checkedNames})
.then((response) => {
console.log(response)
}, (error) => {
// error callback
})
I have then Route::resource('users', 'UsersController'); in api.php so the default route for deleting is:
DELETE| api/users/{user}| users.destroy
and the controller's method is:
|App\Http\Controllers\UsersController#destroy
I am able to delete as expected a user when I pass a single id let's say api/users/12, it gets deleted correctly but when I try to pass the array above things get complicated.
if I try as per axios documentation axios.delete('api/users/', {params: {id: this.checkedNames}}) it looks I am sending this http://lorillacrud.dev/api/users?id[]=21&id[]=20 but I get a 405 method not allowed.
if I try axios.delete('api/users/' + this.checkedNames ) I get http://lorillacrud.dev/api/users/20,21 so in my destroy method I could grab the ids and delete, but I am wondering if this is the correct way to do it?
update
I seemed I made it work but I am not understanding so any help still appreciated to make a sense of what I am actually making work!
So, if change to:
axios.delete('api/users/destroy', {params: {'id': this.checkedNames})
and in my destroy method:
if ($request->id) {
foreach ($request->id as $id) {
User::destroy($id);
}
}
User::destroy($id);
}
So...
// not deletes the user
axios.delete('api/users/destroy', {params: {id: id}})
// ok deletes the users when using request->id in a for loop in the destroy laravel method.
axios.delete('api/users/destroy', {params: {ids: this.checkedNames}})
// ok deletes one user
axios.delete('api/users/' + id)
sorry guys but I have a lot of confusion why and what !!!
The route name is user.destroy why does it work when I pass an array and it does not when I pass a single value, why viceversa the route with method delete will not delete when pass an array ???
Any difference between using api/users/destroy vs api/users only?
Thanks for any help on this!
I also experienced the same problem. This works for me:
deletePost: function(id) {
axios.post('/posts/'+id,{_method: 'delete'})
}
Using axios.post() instead of axios.delete, and sending _method "delete"
It is because of the method signatures. The default delete route when using Resource expects a single parameter. So when doing:
axios.delete('api/users', {params: {'id': this.checkedNames})
you are missing a required parameter. The route definition is
Route::delete('api/users/{id}', 'UserController#destroy');
// You are missing `id` here. So it won't work.
Usually, if you are going to stray away from the default behavior, it is recommended to create your own function. So you could leave the default destroy($id) function as is to delete a single entry and write a new function that will delete many. Start by adding a route for it
Route::delete('api/users', 'UserController#deleteMany');
Then define the function to handle it
public function deleteMany(Request $request)
{
try
{
User::whereIn('id', $request->id)->delete(); // $request->id MUST be an array
return response()->json('users deleted');
}
catch (Exception $e) {
return response()->json($e->getMessage(), 500);
}
}
To summarise, your problem came from route definition. Your route from Axios did not match the route definition from Laravel, hence the 405.
I was having issue to send data as model while making delete request. I found a fix as follows:
deleteCall (itemId, jsonModel) {
return api.delete(`/users/${itemId}/accounts/`, {data: jsonModel})
},
Deleting users in array
Other good option, is to convert javascript array to string, and pass it has the required parameter, instead of passing object. Here the example:
In Vue.js 2.5.17+
//Use the javascript method JSON.stringify to convert the array into string:
axios.delete('api/users/' + JSON.stringify(this.checkedNames))
In Laravel 5.3+
//Resource default route (you don't need to create, it already exists)
Route::delete('api/users/{id}', 'UserController#destroy');
//In laravel delete method, convert the parameter to original array format
public function destroy($id)
{
User::destroy(json_decode($id); //converting and deleting users in array 'id'
}
Deleting single user by id
Just pass the id. You don't need to convert it.
In Vue.js 2.5.17+
axios.delete('api/users/' + id)
In Laravel 5.3+
You can name the parameter as you wish: user, id, item ,...
In Laravel 5.6+ < is named as $id //this can be the id or the user object
In Laravel 5.7+ > is named as $user //this can be the id or the user object
public function destroy($id)
{
User::destroy($id);
}
axios.post('/myentity/839', {
_method: 'DELETE'
})
.then( response => {
//handle success
})
.catch( error => {
//handle failure
})
https://www.mikehealy.com.au/deleting-with-axios-and-laravel/

Not able to use pushPayload in ember

I have to store a data from ajax call to model.Now I am using "pushPayload" to save the data to my model.But it is throwing error
serializer.pushPayload is not a function
In controller I am doing something like this after the ajax call.
currentState.store.pushPayload('discover',result)
serializer (discover.js)
export default DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin,{
isNewSerializerAPI: true,
primaryKey:'pk',
normalize: function(typeClass, hash) {
var fields = Ember.get(typeClass, 'fields');
fields.forEach(function(field) {
var payloadField = Ember.String.underscore(field);
if (field === payloadField) { return; }
hash[field] = hash[payloadField];
delete hash[payloadField];
});
return this._super.apply(this, arguments);
}
});
How do I save the data recieved from server to my model.The reponse is an array of object
store.pushPayload internally uses either application serializer's pushPayload function or the given model's specific serializer's pushPayload function. In your case model specific serializer is of JSONSerializer type which doesn't have the required function.
You can refer JSONAPISerialzer, which has the pushPayload function and try to replica it in your JSONSerializer.

Retrieve values from getJSON() call in jQuery

I have an ajax call in my jquery to my MVC controller:
$.getJSON('/mysite/controller/dosomething', { postId: id }, function (data) {
The 'data' that I am returning is in the form of a JsonResult, and consists of a simple custom object with 1 property called 'Message' and another property called 'Count'. Both of these values are assigned and I am returning them as follows (edited for brevity):
[HttpGet]
public JsonResult DoSomething(int postId)
{
var response = new MyAjaxResponseModel {Message = "Hello world!", Count = 66};
return Json(response, JsonRequestBehavior.AllowGet);
}
In my jQuery, I then want to be able to look at both values in the Json response, but I don't know the proper way to get at these values?
data.Message, data.Count in the callback you're passing to $.getJSON()? To inspect the structure of your data object, you can use console.log(data) (also, in that callback)

Resources