Displaying json data on datatables with laravel resources - laravel

I have some data i have stored in my table and i have cast to array and accessing it in my resource like this
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class JobRequests extends JsonResource
{
public $preserveKeys = true;
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$data = DB::select('select order_data from orders where id=9');
return [
'email' => json_decode($data[0]->order_data)->personal_data->email,
'telephone_number' => json_decode($data[0]->order_data)->personal_data->telephone_number,
'car_registration' => json_decode($data[0]->order_data)->personal_data->car_registration,
'postal_code' => json_decode($data[0]->order_data)->personal_data->postal_address
/**
'commission' => function(){
$final_price = 700;
return (int)$final_price;
}
*/
];
}
}
My data looks like this
{
"personal_data": {
"email": "info#info.com",
"telephone_number": "0999",
"postal_address": "LON",
"car_registration": "GB BHG"
},
"inperson_diagnostic": {
"diagnostic_inspection": "67.30",
"car_wont_start_inspection": "67.30",
"plugin_diagnostic_inspection": "67.30"
},
"tyres": {
"front_wheels": 1,
"rear_wheels": 1,
"wheel_width": 45,
"wheel_profile": 1,
"wheel_rim": 1,
"speed_rating": "w",
"final_price": 90
},
"servicing_and_mot": {
"mot_with_collection_delivery": 75,
"major_service": 304.52,
"full_service": 203.45,
"interim_service": "149.70",
"vehicle_health_check": 50
},
"inspection_services": {
"premium_prepurchase_inspection": 146.38,
"standard_prepurchase_inspection": 104,
"basic_prepurchase_inspection": 86.44
},
"repairs": {
"ABS wheel speed sensor replacement": 964,
"ABS pump replacement": 712,
"Brake pedal switch replacement": 568,
"Air conditioning regas (R1234yf Gas ONLY)": 469
}
}
This is the function i am trying to fetch data with
//Fetch Job Requests
public function jrData(Request $request)
{
//$data = DB::select('select order_data from orders where id=9');
$jobRequest = new JobRequests($request);
$object_json = $jobRequest->toJson();
$object_array = (array)$object_json;
return Datatables::of($object_array)
->addIndexColumn()
->addColumn('action', function($row){
$btn = 'View';
return $btn;
})
->rawColumns(['action'])
->make(true);
}
and this is my blade page
<script>
$(function() {
$('#users-table').DataTable({
processing: true,
serverSide: true,
ajax: '{!! url('jrData') !!}',
columns: [
{ data: 'id', name: 'id' },
{ data: 'email', name: 'email' },
{ data: 'telephone_number', name: 'telephone_number' },
{ data: 'car_registration', name: 'car_registration' },
{ data: 'postal_code', name: 'postal_code' },
{data: 'action', name: 'action', orderable: false, searchable: false}
]
});
});
</script>
This is the data returned by my jrData
{"draw":0,"recordsTotal":1,"recordsFiltered":1,"data":[{"0":"{\"email\":\"info#info.com\",\"telephone_number\":\"0900\",\"car_registration\":\"KGB BHG\",\"postal_code\":\"00200\"}","action":"<a href=\"view_job_request\/\" class=\"edit btn btn-info btn-sm m-2\">View<\/a>","DT_RowIndex":1}],"input":[]}
I get this error on my blade file
DataTables warning: table id=users-table - Requested unknown parameter
'id' for row 0. For more information about this error, please see
http://datatables.net/tn/4
How can i display the data in the datatables?

Ok here is an example:
You have
$data = DB::select('select order_data from orders where id=9');
This really isn't going to give you the data you need.
Try doing this:
$data = YourModel::where('id',$id)->first();
$id is a dynamic id so you can run this to grab anything instead of being static. I'm guessing you are doing a post to get the data, so if you send that through it would be $request->id so you just set it to $id = $request->id; now you're fully dynamic in your eloquent.

Related

How to get the value from another table using id with Ajax and Laravel?

I was trying Yajra Datatable on Laravel and I found this on the tutorial where I get the values from a single table.
I have to compare the values of each column in the 1st table to the 2nd table like for example the 1st tables status is 1, it would check the status types table which status has the id of 1 and in this example 1 is pending so the datatable would be showing "Pending" instead of number 1
Below here is the code from the Controller:
public function index()
{
$documents = Documents::all();
$status = Status::all();
return view('document/index', compact('documents', 'status'));
}
public function getDocs(Request $request)
{
if ($request->ajax()) {
$docs = Documents::latest()->get();
return Datatables::of($docs)
->addIndexColumn()
->addColumn('action', function($row){
$actionBtn = 'Edit Delete';
return $actionBtn;
})
->rawColumns(['action'])
->make(true);
}
}
Here is from the document/index view:
$(function () {
var table = $('.yajra-datatable').DataTable({
processing: true,
serverSide: true,
ajax: "{{ route('documents.list') }}",
columns: [
{data: 'id', name: 'id'},
{data: 'status', name: 'status'}
]
});
});
First Define relation between Status and Documents Model
Status Model:
public function docs(){
return $this->hasMany(Documents::class);
}
Documents Model:
public function state(){
return $this->belongsTo(Status::class, 'status');
# 'status' is the name of foreign key on documents table
}
Documents Controller:
public function getDocs(Request $request)
{
if ($request->ajax()) {
$docs = Documents::with('state')->select('documents.*')->latest();
# Here 'documents' is the name of table for Documents Model
# And 'state' is the name of relation on Document Model.
return Datatables::of($docs)
->addIndexColumn()
->addColumn('status_str', function($row){
# 'name' is the field in table of Status Model
return $row->state->name;
})
->addColumn('action', function($row){
$actionBtn = 'Edit Delete';
return $actionBtn;
})
->rawColumns(['action'])
->make(true);
}
}
Index View:
$(function () {
var table = $('.yajra-datatable').DataTable({
processing: true,
serverSide: true,
ajax: "{{ route('documents.list') }}",
columns: [
{data: 'id', name: 'id'},
{data: 'status_str', name: 'state.name'}
]
});
});

Laravel Yajra Datatables searchable not working on desire column

I have datatables column as such:
var showMasterUserTable = function () {
masterIcon = $('#master_user_table').DataTable({
processing: true,
serverSide: true,
responsive: true,
ajax: {
url: ROOT + 'master-voucher-bit-x/data',
},
columns: [
{
data: 'DT_RowIndex',
name: 'DT_RowIndex',
searchable: false,
orderable: false
},
{
data: 'voucher_code',
name: 'voucher_code',
},
{
data: 'status',
name: 'status',
},
{
data: 'track',
name: 'track',
},
{
data: 'user_use',
name: 'user_use',
orderable: true
},
{
data: 'progress',
name: 'progress',
},
{
data: 'quiz_score',
name: 'quiz_score',
},
{
data: 'urlQr',
name: 'urlQr',
}
]
});
};
As long as i know from the yajra and datatables docs that searchable and orderable is default to be true when it remains unwritten, i have encounter the issue where searchable only search for voucher_code column no matter if i set all the searchable to true. I want to search for user_use column instead. If i set all the searchable to false, the table data cannot be loaded. How should i overcome it? Here's my controller code:
{
$model = VoucherBitX::select('voucher_bit_x.*', 'users.email')
->join('users', 'voucher_bit_x.user_id', '=', 'users.id')
->orderBy("voucher_bit_x.redeem_at","DESC");
return DataTables::of($model)
->addColumn('status', function ($data) {
if($data->status > 0)
$status = '<div><span class="badge badge-success"> Available </span></div>';
else
$status = '<div><span class="badge badge-danger"> Not Available </span></div>';
return $status;
})
->addColumn('urlQr', function ($data) {
$user = UserApp::find($data->user_id);
$a = "";
if(!empty($user) && isset($user->ref_id)){
$quiz = QuizScore::where("track_id",$data->track_id)->where("user_id",$data->user_id)->first();
if($quiz && $quiz->status){
$track = Track::find($data->track_id);
$urlQr = 'https://xxx.id/api/certificate/'.base64_encode(json_encode(["user_id"=>$user->id,"slug"=>$track->slug,"track_id"=>$track->id]));
$a = 'Download Certificate';
}
}
return $a;
})
->addColumn('quiz_score', function ($data) {
$score = 0;
$quiz = QuizScore::where("track_id",$data->track_id)->where("user_id",$data->user_id)->first();
if($quiz){
$score = $quiz->score;
}
return $score;
})
->addColumn('progress', function ($data) {
$progress = 0;
$solve = Track::userProgress($data->user_id,$data->track_id);
if(!empty($solve)){
$progress = $solve;
}
return $progress."%";
})
->addColumn('user_use', function ($data) {
$user = UserApp::find($data->user_id);
if(!empty($user))
return $user->name." (".$user->email.")";
return '-';
})
->addColumn('track', function ($data) {
$track = Track::find($data->track_id);
return isset($track->title)?$track->title:"";
})->rawColumns(['quiz_score','status','user_use','track','urlQr'])
->addIndexColumn()->make(true);
}
*Edit:
I have realized that datatables returned a response that included used query like this:
New question: just where the hell that query json field configuration? On my eloquent query above there is no such thing as where and like query. Haven't found that things both in yajra and datatables documentation. What i want is to modify the where field to users.email instead voucher_bit_x.voucher_code
use columns.searchable
Using this parameter, you can define if DataTables should include this column in the filterable data in the table. You may want to use this option to disable search on generated columns such as 'Edit' and 'Delete' buttons for example.
$('#example').dataTable( {
"columnDefs":
[
{ "searchable": false, "targets": 0 }
]
});
This will disable the search of multiple columns as specified n the target. If you want multiple columns then try using
{ "searchable": false, "targets": [0,1,2] }
Where targets 0 1 and 2 are number of columns starting index from 0

yajra/laravel-datatables, Reply Slow

Summary of problem or feature request
The reply o load datatable is very slow, betwen 3-5seg
How can I optimize the data load?
when I did not use server inside it was much faster..
first of all, Thanks
Code snippet of problem
Controller
public function list_user(){
$users = User::all();
$users->each(function ($users)
{
$users->role;
});
return datatables()->collection($users)->toJson();
}
Js
function activar_tabla_users() {
$('#DataTableUser').DataTable({
"processing" : true,
"serverSide" : true,
"searchDelay" : 500,
"responsive": {
orthogonal: 'responsive'
},
"language": {
"url": '{!! asset('/plugins/datatables.net/latino.json') !!}'
} ,
"lengthMenu": [5,10, 25, 50, 75 ],
"ajax":'{!! url('admin/list_user') !!}',
columns: [
{data: 'id' },
{data: 'username'},
{data: 'name',
render: function (data, type, row, meta) {
return row.name + ' ' + row.lastname;
}
},
{data: 'email'},
{data: 'role.name',
render: function(data, type, row, meta) {
var html = ''
if ( row.role.name == 'Administrador' )
{
html = '<span class="label label-danger" > <label style="width:80px;"> '+row.role.name+' </label></span>';
}else {
html = '<span class="label label-primary" > <label style="width:80px;"> '+row.role.name+' </label></span>';
}
return html;
}
}
}],
});
}
activar_tabla_users();
You are using server side to get table data. Don't call all() as it will get all.
Replace:
$users = User::all();
With:
$users = User::query();
This only renders the required data in data-table page.
And, don't use loop to get role. Use eager loading using with();
$users = User::query()->with('role');
$users = User::all();
$users->each(function ($users)
{
$users->role;
});
with this the following?
$users = User::with('role');
Datatable adds pagination options automatically. if you use all() it calls all the data from the table.
Another thing is did you checked that it takes 2/3sec to get data from the server or does it takes this time to format the data in the view?
replace
$users = User::all();
$users->each(function ($users)
{
$users->role;
});
with this:
$users = User::with('role')->get();
This will use one db request instead of over 1k requests (you were making a call for each user to get their role). If you display all 1300 users at once, only request the "page" you need with laravels built in pagination, https://laravel.com/docs/5.6/pagination#paginating-eloquent-results

Call to a member function getQuery() on array

Trying to do with datatables in laravel:
Error: Call to a member function getQuery() on array in laravel datatables
Here is Laravel Code:
Controller:
public function get_all_course_requests() {
$course_request = new CourseRequest();
$request_details = $course_request->get_all_course_requests();
$i = 0;
foreach ($request_details as $request) {
$request_details[$i]->sr_no = $request->id;
$request_details[$i]->l_fname = $request->l_fname;
$request_details[$i]->l_lname = $request->l_lname;
$request_details[$i]->l_mail = $request->l_mail;
$request_details[$i]->name = $request->name;
$request_details[$i]->request_date = $request->request_date;
$request_details[$i]->action = $request->id;
$i++;
}
return Datatables::of($request_details)
->filterColumn('l_fname', 'l_lname', 'name','course_name','request_date')
->make(true);
}
Model:
function get_all_course_requests($status='0') {
// DB::enableQueryLog();
$course_request = new CourseRequestModel;
$my_team_ids = $course_request->get_my_team_learner_ids();
return DB::table('course_request')
->select('login_details.l_fname','login_details.l_lname','login_details.l_mail','course_request.id','multilevel_course.name','course_request.request_date')
->whereIn('login_details.l_id', $my_team_ids)
->where('course_request.status', $status)
->join('login_details', 'login_details.l_id','=', 'course_request.user_id')
->join('multilevel_course', 'multilevel_course.id','=','course_request.course_id')
->whereIn('enrollment_policy',array('2','3') )
->get();
}
Here is JS Code:
$(function() {
$('#course_requests_table').DataTable({
processing: true,
serverSide: true,
ajax: BASE_URL + '/get_course_requests',
order: [],
columns: [
{data: "view", orderable: false,
render: function(data, type, row) {
return '<input type="checkbox" class="case" name="row_ids[]" value="' + data + '">';
}
},
{data: 'l_fname', name: 'l_fname'},
{data: 'l_lname', name: 'l_lname'},
{data: 'l_mail', name: 'l_mail'},
{data: 'name', name: 'name'},
{data: 'request_date', name: 'request_date'},
{data: 'action', orderable: false,
render: function(data, type, row) {
return '<a style="cursor:pointer" OnClick="delete_mail(' + data + ')"><i class="fa fa-trash"></i></a>';
}
}
]
});
});
Whats going wrong with code? and what to be done to solve this?
Solved:
Solution: converted array to Collection using collect()
$request_details = $course_request->get_all_course_requests();
$request_details= collect($request_details);
$i = 0;
foreach......

Ajax query works when adding new post but doesn't work when update an entity

I have two Select box one for the Countries and the second for the cities and the second one depends from the selected choice of the first one.
I the code is as the example Dynamic Generation for Submitted Forms in the documentation http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data
All things work fine when adding a new post , but when trying do update a post, the Ajax query to display cities doesn't work .
This is the controller
// newAction
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
*/
public function newAction(Agence $agence, Request $request)
{
$em = $this->getDoctrine()->getManager();
$travel = new Travel();
$form = $this->createForm(new TravelType($agence), $travel);
if ($request->getMethod() == 'POST')
{
//....
}
return $this->render('AppBundle:Dashboard/Travel:new.html.twig',
array(
'form' => $form->createView() ,
'agence' => $agence,
));
}
//editAction
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
* #ParamConverter("travel", options={"mapping": {"travel_id":"id"}})
*/
public function editAction(Travel $travel, Agence $agence, Request $request)
{
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new TravelEditType($agence), $travel);
if ($request->getMethod() == 'POST'){
//....
}
return $this->render('AppBundle:Dashboard/Travel:edit.html.twig',
array(
'form' => $form->createView() ,
'travel' => $travel,
'agence' => $agence,
));
}
travelType and ti works good
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class TravelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//....
$formModifier = function (FormInterface $form, Country $country = null) {
$cities = null === $country ? array() : $country->getCities();
$form->add('destination', 'entity', array(
'class' => 'AppBundle:CityWorld',
'choices' => $cities,
'multiple' => false,
'expanded' => false,
'property' => 'name',
'label' => 'Destination',
'attr' => array('class' => 'col-xs-10 col-sm-10', 'placeholder' => 'Destination'),
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getCountry());
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $country);
}
);
$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
$event->stopPropagation();
}, 90000000000000); // Always set a higher priority than ValidationListener
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Travel'
));
}
public function getName()
{
return null;
}
}
This is TravelEditType
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class TravelEditType extends TravelType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options) ;
}
public function getName()
{
return null;
}
}
This is the form and javascript code
<form method="post" action="" class="form-horizontal" role="form" {{ form_enctype(form) }} >
//.............
</form>
<script type="text/javascript">
var $county = $('#country');
$county.change(function () {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
var data = {};
data[$county.attr('name')] = $county.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: data,
success: function (html) {
// Replace current position field ...
$('#city').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#city')
);
// Position field now displays the appropriate positions.
}
});
});
Try it without parameter in URI:
dashboard_city_ajax:
path: /citiies/ajax
defaults: { _controller: AppBundle:TravelDashboard:ajaxCities }
And send data with POST:
$.ajax({
url: '{{ path('dashboard_city_ajax') }}',
type: 'POST',
data: { agence_slug: '{{ agenceSlug }}' },
You can receive it in controller:
$request->request->get('bar', 'default value if bar does not exist');
The problem is in your route matching. There is many way to solve problem. Try just include in your ajax route requirements for matching route or in $.ajax function use another route, for example
The simplest way for you (if you don't want rebuild your controller) is just rebuild your route and put in the first place your ajax route like :
dashboard_city_ajax:
path: /{ajax}/{agence_slug}/citiies
defaults: { _controller: AppBundle:TravelDashboard:ajaxCities }
requirements:
ajax: ajax
$.ajax({
url: '{{ path('dashboard_city_ajax', {'agence_slug': agence.slug, 'ajax': 'ajax' }) }}',
type: 'POST',
data: data,
But the right way IMHO is get your data from request. For example
vplanning_ajax:
path: /ajax
defaults: { _controller: VplanningPageBundle:Page:Ajax }
function getData(init) {
$.post(
{{ path('vplanning_ajax') }},
{
agence_slug: agence.slug,
yourdata2: 'yourdata2
} ,
function ( data ) {
handleData(data);
}
);
}
And in your Controller your just do
$agence_slug = $this->request->request->get('agence_slug');
$yourdata2 = $this->request->request->get('yourdata2);
...

Resources