Laravel- datatables inline editing and use autocomplete for multitables - php

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

Related

Get All name From Table1 Where id (Separated by Comma) from Table2 - Ignited Datatables Server Side Using Codeigniter

I get stuck with my code. If you know about it, please respond to this question, cause I very need your help.
I have 2 tables (proposal and surveyor).
Proposal field :
proposal_id, proposal_name, surveyor_proposal
Example row : ('1', 'this is proposal name', '3,18,22')
As you can see, this is have 3 surveyor id separated by comma)
Surveyor field :
surveyor_id, surveyor_name
Example row :
('3', 'Randy')
('18', 'Bella')
('22', 'Zidan')
! here it is, I want to print out Randi, Bella, and Zidan in the view table
Model.php :
function get_all_datatables($x) {
$this->datatables->select('proposal_name, surveyor_name');
$this->datatables->from('proposal');
$this->datatables->join('surveyor','surveyor_id = surveyor_proposal','left');
return $this->datatables->generate();
}
Controller.php :
function get_data_json($x) { //get product data and encode to be JSON object
header('Content-Type: application/json');
echo $this->m_bl->get_all_datatables($x);
}
View.php :
$("#table").dataTable({
initComplete: function() {
var api = this.api();
$('#table_filter input')
.off('.DT')
.on('input.DT', function() {
api.search(this.value).draw();
});
},
oLanguage: {
sProcessing: "loading..."
},
processing: true,
serverSide: true,
ajax: {"url": "<?= base_url('dashboard/bl/get_data_json/'.$uri); ?>", "type": "POST"},
{"data": "proposal_name"},
{"data": "surveyor_name"},
rowCallback: function(row, data, iDisplayIndex) {
var info = this.fnPagingInfo();
var page = info.iPage;
var length = info.iLength;
$('td:eq(0)', row).html();
}
});
Update!
I've been add 1 table junction, the fields is :
proposal_id_junction, surveyor_id_junction
Example Value :
('1','3') --> as Randy
('1','18') --> as Bella
('1','22') --> as Zidan
And i update my table join :
$this->datatables->join('junction','proposal_id_junction = proposal_id','left');
$this->datatables->join('surveyor','surveyor_id = surveyor_id_junction','left');
But, thats showing same proposal and different surveyor name, like this :
'this is proposal name','Randy'
'this is proposal name','Bella'
'this is proposal name','Zidan'
I want to thats view like this :
'this is proposal name','Randy, Bella, Zidan'
Please help.

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

Filter Index-2 to Index+2 in Datatables

I'm currently displaying a table returning player rankings and highlighting the current player row. What I would like to achieve is let's say display on 5 rows and center the current player at the center.
If the current player ranking is 100th, I want to display player ranks 98 to 102. Currently it will display rank 1 to 5.
I can't find a want to "center my results" on the current player ranking.
My current table is displayed with this code:
$.ajax({
url: "myController/getDataTable",
method: 'post',
dataType: 'json',
success: function (values) {
var table = $('#myTableLeaderboard').DataTable({
paging: true,
pageLength: 5,
sort: true,
searching: true,
data: values['data'],
ordering: true,
aoColumns: [
{ "data": "ranking" },
{ "data": "cash" },
{ "data": "staff_count" }
// more columns...
],
"createdRow": function ( row, data, index ) {
$currentUserId = $('#currentUserId').attr('value');
if ( data.id_player == $currentUserId ) {
$('td', row).addClass('bold');
}
}
});
$('#myTableLeaderboard_filter').switchClass( 'dataTables_filter', 'dataTables_filter_show' );
}
});
My server side PHP function returns two arrays, one containing the data for the table and one variable containing the current player rank:
{"data":
[{"cash":"606, "id_player":"61","staff_count":null,"ranking":1},
{"cash":"30","id_player":"63","staff_count":null,"ranking":2},
...more players....],
"current_id_player":"67",
"current_player_ranking":3
}
I looked into the Custom filtering - range search page but I'm not sure that's what I should look into and how to approach it.
Finally, paging is enabled so if the player navigates to another page, the results won't be "centered" on him anymore.
I found the solution with adding:
displayStart: values.current_player_ranking-2,
And completed with jumpToData plugin
$('#myTableLeaderboard thead').on('click', 'th', function () {
table.page.jumpToData( $currentUserId, 9 );
} );
table.page.jumpToData( $currentUserId, 9 );

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(),

can't add data to jqGrid from php within json format

Hello StackOverFlow nation . I'm trying to add information to jqGrid , which is retrieved from MySQL database. I've two files => index.html and data.php (both in the same directory)
index.html source =>
<script type="text/javascript">
$(function(){
$("#jqGrid_tb").jqGrid({
url: "data.php",
datatype: "json",
sortable: true,
height: "auto",
colNames: ["Name","Surname","Birth Year","Famous Film"],
colModel: [
{name: "name", index: "name", width: "150"},
{name: "surname", index: "surname", width: "150"},
{name: "b_year", index: "year", width: "150"},
{name: "film", index: "film", width: "200"}
],
rowNum: 5,
rowList: [5,10,15],
viewrecords: true,
pager: $("#pager"),
caption: "Famous Actors",
}).navGrid("#pager");
});
</script>
<div id="grid">
<table id="jqGrid_tb"></table>
<div id="pager"></div>
</div>
data.php source =>
include ("JSON.php");
$json = new Services_JSON();
$con = new mysqli("host","user","pswd","db");
if (!$con->connect_errno){
if ($r = $con->query("SELECT * FROM actors")){
while ($row = $r->fetch_assoc()){
$info[] = array(
"name" => $row[name],
"surname" => $row[surname],
"b_year" => $row[b_year],
"film" => $row[film],
);
}
$r->free();
}
}
echo $json->encode($info);
if (isset($con)){
$con->close();
}
jqGrid is shown without any information in index.html file , also when opening data.php file information is successfully encoded into JSON format , whats wrong I can't understand . Please help , thanks ...
Your response format is wrong. You can go to jqGrid Demos page where you will find a sample for PHP/MySQL after expanding Loading Data and then choosing JSON Data.
The proper format of data should look like this:
{
"total": "1",
"page": "1",
"records": "2",
"rows": [
{ "name": "Robert", "surname": "De Niro", "b_year": "1943", "film": "Once Upon A Time In America" },
{ "name": "Al", "surname": "Pacino", "b_year":"1971", "film": "Scent Of A Woman"}
]
}
Where:
total --> total count of pages
page --> current page number
records --> total count of records
rows --> the rows of data
Also if you want rows to be objects, you need to disable repeatitems in jqGrid jsonReader options:
$("#jqGrid_tb").jqGrid({
...
jsonReader: { repeatitems: false }
});
It is also adviced for rows to have unique id for later reference.
You should include
jsonReader: {
repeatitems: false,
root: function (obj) { return obj; },
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.length; }
}
as additional option of jqGrid is you don't want to change format of input data. Moreover you should specify which values should assign jqGrid as id attribute of the row. You can include additional id property as additional property of every returned item or you can add key: true property to the column (in colModel) which contains unique values. For example if you can guarantied that the values from "name" are already unique then you can include key: true property in definition of "name" column.
Additionally you can consider to use loadonce: true option of jqGrid. In the case the full data of the grid will be loaded at once and the sorting, paging and searching (filtering) of data will be implemented by jqGrid on the client side without needs to implement some additional code on the server side. You should don't use the option in case of large number of rows (many hundred or many thousand rows) in the grid.

Categories