Process data after using Datatables server side on Laravel 5.3 - php

I have a table in database with 73k records.
So I want to show it in only one table on view using Datatables.
This is table should be:
Datatables in client side
I already have a table with datatables but It's limited item.
The first column is not in database,
"Show Image" column is special feature, when manager hover over this text, the image shown
I want to use datatable in server side to load all data with changing the appearance.
So I make a controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use Yajra\Datatables\Datatables;
use App\Models\GS1;
class DataTablesController extends Controller
{
private $sa24Repository;
// function __construct(SA24Repository $sa24Repository)
// {
// $this->sa24Repository = $sa24Repository;
// }
public function getIndex() {;
return Datatables::of(Product::query())->make(true);
}
}
?>
with a simple view:
Products table
It work well but when I type in search input, It search all column.
And I have to add this code to using filter:
<script>
$('.testTable').dataTable();
$.fn.dataTable.ext.errMode = 'throw';
$('.testTable').dataTable({
destroy: true,
processing: true,
serverSide: true,
ajax: '/datatables',
columns: [
{data: 'gtin'},
{data: 'brand_name'},
{data: 'description_short'}
]
});
</script>
If I remove this codes:
columns: [
{data: 'gtin'},
{data: 'brand_name'},
{data: 'description_short'}
]
When I search Browser logged:
Uncaught Error: DataTables warning: table id=DataTables_Table_0 - Requested unknown parameter '0' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4
at Ae (all.js?v=1484881746:6)
at k (all.js?v=1484881746:5)
at j (all.js?v=1484881746:5)
at M (all.js?v=1484881746:5)
at U (all.js?v=1484881746:6)
at all.js?v=1484881746:5
at d (all.js?v=1484881746:5)
at Object.success (all.js?v=1484881746:5)
at d (all.js?v=1484881746:2)
at Object.fireWith [as resolveWith] (all.js?v=1484881746:2)
and I can't search anything
So could you help me to using datatable to search any columns I want to,
and I don't have to add this snippet in script:
columns: [
{data: 'gtin'},
{data: 'brand_name'},
{data: 'description_short'}
]

Well the columns array determines what to display in the Datatables. Think about it, if the client doesn't even know what columns to display, how would it render the table?
If you want to only search limited columns, you can add searchable: false in columns like so (say you dont want to search based on brand name):
columns: [
{data: 'gtin'},
{data: 'brand_name', searchable: false},
{data: 'description_short'}
]

I have already fixed this by modifying in DatatableController. And it worked well

Related

Laravel Spatie - Why does the [object Object] are being displayed not its exact value from database?

I am using Spatie for logging activities in my web site. I created a table where the data from activity_log database table will be displayed. There's no problem in retrieving the data from database but my problem is that whenever I display the values from properties column it only displays [object Object].
Here's what the data table looks like:
While it's actual values in the database table of activity_log is this:
Here's my snippet code from my controller:
public function datatable_Activities()
{
$data = Activity::all()->where('causer_id', '=', Auth::user()->id);
return Datatables::of($data)->make(true);
}
Snippet code for displaying the data in my blade file:
<script>
$(function () {
$("#activity_table_log").DataTable({
responsive:true,
processing:true,
pagingType: 'full_numbers',
stateSave:false,
scrollY:true,
scrollX:true,
ajax:"{{route('datatable_Activities')}}",
order:[0, 'desc'],
columns:[
{data:'log_name', name: 'log_name'},
{data:'description', name: 'description'},
{data:'subject_id', name: 'subject_id'},
{data:'properties', name: 'properties'},
{data:'created_at', name: 'created_at', searchable: false, sortable:false},
]
});
});
</script>
I already tried json_decode() but unfortunately it is not working..
How to display it properly like the values stored in properties
column in database not the [object Object]?
However when I check the response in Developer's Tool it retrieves the values of properties exactly from the database.
Here's the example nested JSON object I am trying to put in the data table:
{
"id":6,
"log_name":"PurchaseH",
"description":"A purchase h has been updated",
"subject_id":1,
"subject_type":"App\\Model\\Purchase\\PurchaseH",
"causer_id":1,
"causer_type":"App\\User",
"properties":{
"attributes":{
"total":1250000
},
"old":{
"total":null
}
},
"created_at":"2020-06-14T09:04:34.000000Z",
"updated_at":"2020-06-14T09:04:34.000000Z"
},
P.S. I'm Using latest Google chrome, Laravel Framework and Spatie.

laravel datatable take long time to load data

I am trying to display database table to laravel datatable using below code but laravel datatable taking long time to load data.
I have approx 700000 records in database. How to decrease time of load data?
Code
web.php
Route::get('home', 'HomeController#index')->name('home');
HomeController.php
public function index()
{
$campaigns = TonicData::select('campaign')->distinct()->get();
if (request()->ajax()) {
$data = \DB::table('tonic_data')
->whereNotNull('subid4')
->where('subid4', '!=', '')
->select('subid4')
->groupBy('subid4')
->selectRaw('sum(view) as sum_of_views, sum(term_view) as sum_of_term_views,
sum(add_click) as sum_of_add_click, sum(revenue_usd) as sum_of_revenue,
(sum(revenue_usd)/sum(view)*1000) as rpm')
->when((request()->has('selectedCampaign') && request()->get('selectedCampaign') != ''), function ($query) {
$query->whereIn('campaign', request()->get('selectedCampaign'));
})
->when((request()->has('selectedDateRange') && request()->get('selectedDateRange') != ''), function ($query) {
$query->whereBetween('day_date', [request()->get('selectedDateRange')['fromDate'], request()->get('selectedDateRange')['toDate']]);
});
return DataTables::of($data)
->addIndexColumn()
->make();
}
return view('dashboard', compact('campaigns'));
}
dashboard.blade.php
<script type="text/javascript">
$(document).ready(function() {
$('#datatable').dataTable({
responsive: true,
processing: true,
serverSide: true,
ajax: '{{ route('home') }}',
columns: [
{data: 'DT_RowIndex', orderable: false, searchable: false},
{data: 'subid4', name: 'subid4'},
{data: 'sum_of_views', name: 'sum_of_views', searchable: false},
{data: 'sum_of_term_views', name: 'sum_of_term_views', searchable: false},
{data: 'sum_of_add_click', name: 'sum_of_add_click', searchable: false},
{data: 'sum_of_revenue', name: 'sum_of_revenue', searchable: false},
{data: 'rpm', name: 'rpm', searchable: false}
]
});
});
</script>
sql code
query 1:
select count(*) as aggregate
from ( SELECT `subid4`,
sum(view) as sum_of_views,
sum(term_view) as sum_of_term_views,
sum(add_click) as sum_of_add_click,
sum(revenue_usd) as sum_of_revenue,
(sum(revenue_usd)/sum(view)*1000) as rpm
from `tonic_data`
where `subid4` is not null
and `subid4` != ?
group by `subid4`
) count_row_table
query 2:
select `subid4`, sum(view) as sum_of_views, sum(term_view) as sum_of_term_views,
sum(add_click) as sum_of_add_click, sum(revenue_usd) as sum_of_revenue,
(sum(revenue_usd)/sum(view)*1000) as rpm
from `tonic_data`
where `subid4` is not null
and `subid4` != ?
group by `subid4`
limit 10 offset 0
Thanks in advance!
To summarize the discussion, as your query try to get all 700k records at once, no wonder it takes a long time.
Al though you are showing only a limited number of records while rendering the page, technically query gets all records on page load itself.
Action Required
Minimize the below section:
->selectRaw('sum(view) as sum_of_views, sum(term_view) as sum_of_term_views,
sum(add_click) as sum_of_add_click, sum(revenue_usd) as sum_of_revenue,
(sum(revenue_usd)/sum(view)*1000) as rpm')
Instead of sum up all these values on the fly, maintain a separate table and store all these values when any record gets altered in the tonic_data. There are callback functions as per this answer.
Instead of datatables use laravel pagination and sorting which will perform on server side that controls loading the huge data on page load.
try to implement date based or other possible filters.
Looks like Laravel is running the same query twice -- once to get a row count, once to get the first 10 rows.
Because of the GROUP BY, the LIMIT 10 has little effect on the speed. This is because it must gather lots of rows, then do the grouping, and only finally deliver 10 rows.
The first query (to get the count) could be simplified and greatly sped up by changing to
select count(DISTINCT subid4) as aggregate
from `tonic_data`
where `subid4` is not null
and `subid4` != ?
and having
INDEX(subid4)
Or forego of the count (if Laravel lets you do that).
Please provide SHOW CREATE TABLE tonic_data; I may have further tips.
First of all I suggest looking into your query performance and try to optimize your query.
Secondly jquery datatables plugin has a feature (named as pipeline) to cache number of pages to reduce ajax calls. So this way let's say on first request if you have cached 10 pages, then it won't make another request to server until the 11th page is accessed and this goes on.
So on client side your ajax will be updated to
<script type="text/javascript">
$(document).ready(function() {
$('#datatable').dataTable({
responsive: true,
processing: true,
serverSide: true,
ajax: $.fn.dataTable.pipeline({
url: '{{ route('home') }}',
pages: 20 // number of pages
})
});
});
</script>
For more help on pipeline, please refer https://datatables.net/examples/server_side/pipeline.html

Laravel- datatables inline editing and use autocomplete for multitables

I have a complicated problem, I have a table that contains data as Im using datatable, table Checks have relationship with other table Vendors
what I want just when click on cell vendor_id make it editable and use autocomplete function to fill or edit current data.
I want table to be editable like this example
https://editor.datatables.net/examples/inline-editing/simple
my table screenshot
Check table:
details
description
vendor_id
Vendors table:
vendor_id
vendor_name
now the name of vendor appears in the datatable but dont know why its inside brackets and "" [{"vendor_name":"Raul"}]
so All I want just to show vendor_name and edit it using autocomplete and to store it in the Check Table by storing vendor_id not vendor name
Ajax
var oTable = $('#users-table').DataTable({
dom: 'flBrtip',
stateSave: true,
paging: true,
pagingType: 'simple_numbers',
processing: true,
serverSide: true,
ajax: {
url: 'custom-filter-data',
data: function(d) {
d.start_date = $('input[name=start_date]').val();
d.end_date = $('input[name=end_date]').val();
}
},
columns : [
{data: 'details', name: 'details'},
{data: 'description', name: 'description'},
{data: 'vendor_id',name:'vendor_id'},
{data: 'category_id',name: 'category_id'},
],
pageLength: 10,
});
oTable.draw();
Controller
public function getCustomFilterData()
{
$arrStart = explode("/", Input::get('start_date'));
$arrEnd = explode("/", Input::get('end_date'));
$start = Carbon::create($arrStart[2], $arrStart[0], $arrStart[1], 0, 0, 0);
$end = Carbon::create($arrEnd[2], $arrEnd[0], $arrEnd[1], 23, 59, 59);
$orders = Checks::between($start, $end);
return Datatables::of($orders)->editColumn('vendor_id', function ($user)
{
$vendor =Vendors::select('vendor_name')->where('vendor_id',$user->vendor_id)->get();
return ( $vendor);
}) ->make( TRUE );
}
You're using ->get(); which returns and array and thus the []
If you only want one column (vendor_name) write it like this.
$vendor =Vendors::where('vendor_id',$user->vendor_id)->first();
return $vendor ? $vendor->vendor_name : '';
Explanation of get and first differences: https://laravel.com/docs/5.5/queries#retrieving-results

Pass parameter on Extjs 6

I am new in Extjs 6 but I want to pass parameter to php when grid row is clicked. Here is my code and its is complaining on php that the parameter is undefined. Please assist...
xtype: 'grid',
store: {
type: 'myComment',
autoLoad: true,
autoDestroy: true,
extraParams:{
employee: record.get("employee")
}
},
columns: [
....
]
Please help I've been working on this one for days
extraParams belong to the proxy configuration from your store.
In your case you should do something like this:
{
xtype: 'grid',
store: {
type: 'myComment',
autoLoad: true,
autoDestroy: true,
proxy: {
type: 'ajax',
extraParams:{
employee: record.get("employee")
}
}
},
columns: [....]
}
Here are some more informationen on this:
http://docs.sencha.com/extjs/6.5.0/classic/Ext.data.proxy.Ajax.html#cfg-extraParams
Since you are using ExtJs 6, it is recommended to use the MVVM architecture.
If you do not already know, I would recommend following instructions from Sencha:
http://docs.sencha.com/extjs/6.5.0/guides/application_architecture/application_architecture.html
In your case you can separate the definition of the store from the view. Furthermore it would then be possible to change simple parameters in the view or also in the store using binding.

Eager Load Dynamic Attribute in Laravel for jQuery Datatable

I have a Hotel Model, which hasMany Guests, which in turn has two dynamic attributes as follows.
public function getNameAttribute(){
return $this->user->name;
}
public function getEmailAttribute(){
return $this->user->email;
}
Now I prefer to fetch them as $hotel->guests()->with('user'). Now when I use it for Datatable, I am not able to get the name & email in the view, for obvious reasons. So my question is, Can I eager-load the name & email attributes, so that whenever the guest model gets fetched, the said attributes are available.
Please note, I don't return it asArray or asJson, hence the concept of $attributes array doesn't apply (at-least as far as I know).
The Controller has the following code:
return Datatables::of($guests)
->addColumn('email',function($guest){
return $guest->email;
})
->addColumn('name',function($guest){
return $guest->name;
})->make(true);
However, the datatable cannot search for name or email because they are not available in database.
The jquery datatable code I use is
$(function() {
$('#guest-table').DataTable({
processing: true,
serverSide: true,
ajax: '{!! route('guests.data') !!}',
columns: [
{ data: 'name', name: 'name', orderable: false },
{ data: 'email', name: 'email', orderable: false},
{ data: 'mobile', name: 'mobile', orderable: false}
]
});
});
I use Laravel 5 and yajra/laravel-datatables package
as per the Yajra, Laravel document, you have to call the property of the related model in this way,
{data: 'relation_name.column', name: 'relationName.column'}
so in your case it will be like this,
{data: 'user.name', name: 'user.name'}
{data: 'user.email', name: 'user.email'}
User double quotes here, I will work if this code is inside blade file
ajax: "{!! route('guests.data') !!}",
If you have external js file then use like this
Create a hidden field in blade file
<input type="hidden" id="route_url" value="{!! route('guests.data') !!}">
And in js file take route url by id
ajax: $("#route_url").val(),

Categories