I'd like to pass a SQL query to a Javascript function, found in my view, which will populate a HTML table using the DataTables API. I'm having trouble converting the object array into plain JSON. How would I go about doing so?
[web.php]
Route::get('/admin', function () {
$users = DB::connection('mysql')->select('SELECT * FROM users');
return view('admin', compact('users'));
});
[admin.blade.php] (HTML)
<div class="row">
<div class="col-lg-6">
<div class="card mb-3">
<div class="card-header"><i class="fa fa-user"></i> Users</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-striped table-compact" width="100%" id="userTable" cellspacing="0"></table>
</div>
</div>
</div>
</div>
</div>
[admin.blade.php] (Javascript)
<script type="text/javascript">
$(document).ready(function() {
$('#userTable').DataTable( {
"scrollX": true,
"scrollY": '55vh',
"scrollCollapse": true,
"paging": false,
dom: 'ft',
"aaData": "{{ $users }}",
"aoColumns": [
{ "sTitle": "Name", "mData": "name" },
{ "sTitle": "Email", "mData": "email" },
]
} );
} );
</script>
[Example JSON object/array returned from database]
array:1 [
0 => {#195
+"id": 1
+"name": "Josh_W"
+"email": "user#email.com"
+"group": "Admin"
+"level": 5
+"password": "PASSWORD"
+"remember_token": null
+"created_at": "2017-10-12 14:42:38"
+"updated_at": "2017-10-12 14:42:38"
}
]
The select() method returns an array. You need to collect() the array and then call toJson():
<script type="text/javascript">
$(document).ready(function() {
$('#userTable').DataTable( {
"scrollX": true,
"scrollY": '55vh',
"scrollCollapse": true,
"paging": false,
dom: 'ft',
"aaData": {!! collect($users)->toJson() !!},
"aoColumns": [
{ "sTitle": "Name", "mData": "name" },
{ "sTitle": "Email", "mData": "email" },
]
} );
} );
</script>
To avoid escaping your JSON use the {!! !!} syntax.
See the Laravel documentation on collections and displaying data on views for reference.
Related
I am beginner webdeveloper. I use in my project Laravel 8 and Vue.
I have this code:
<template>
<div class="sm:bg-transparent pt-6 md:mt-16 w-full px-4 md:px-0">
<h1 class="text-dark text-4xl sm:text-3xl font-medium sm:text-center mb-6">{{ __('Archiwum') }}</h1>
<preloader
v-if="isLoadingInProgress"
class="py-8"
:class="preloaderClass"
/>
<div class="text-center" v-if="gasmeters.length == 0 && !isLoadingInProgress">
{{ __('Nie posiadasz jeszcze żadnych odczytów') }}
</div>
<div v-if="gasmeters.length">
<div class="bg-white rounded border border-stroke flex items-start p-6"
v-for="(gasmeter, index) in gasmeters"
v-bind:key="`gasmeter-${index}`">
<div class="mr-6">
<img class="mb-2" :src="gasmeters.img"/> {{ gasmeters }}
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Lipiec 2020 (#123)</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Stan:</span> <span>2120</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Data:</span> <span>2020.01.12</span>
</div>
<div class="w-1/5">
<span class="text-xl">Zgłoszone przez aplikację</span>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import Preloader from "#/common/components/Preloader";
export default {
components: {
Preloader
},
mounted() {
this.loadGasmeters();
},
data() {
return {
gasmeters: [],
isLoadingInProgress: false,
}
},
computed: {
preloaderClass() {
return this.gasmeters.length > 0
? ""
: "loading--transparent loading--block";
}
},
methods: {
loadGasmeters() {
this.isLoadingInProgress = true;
axios
.get(route('api.archive.list'))
.then(response => {
this.gasmeters = _.get(response, "data.data", []);
console.log(this.gasmeters);
})
.catch(error => {
console.log(error);
})
.then(() => {
this.isLoadingInProgress = false;
});
},
}
}
</script>
My php return me:
{
"data": [
[
{
"id": 1,
"value": "99.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Stan pobrany z systemu BAŁTYKGAZ",
"img": "img/icons/crm.svg",
"created_at": "2020-10-21T15:09:22.000000Z"
},
{
"id": 2,
"value": "109.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Zgłoszone przez aplikację",
"img": "img/icons/cms.svg",
"created_at": "2020-10-21T17:02:18.000000Z"
}
]
]
}
I have problem with my part this code:
<div v-if="gasmeters.length">
<div class="bg-white rounded border border-stroke flex items-start p-6"
v-for="(gasmeter, index) in gasmeters"
v-bind:key="`gasmeter-${index}`">
<div class="mr-6">
<img class="mb-2" :src="gasmeters.img"/> {{ gasmeters }}
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Lipiec 2020 (#123)</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Stan:</span> <span>2120</span>
</div>
<div class="w-1/5">
<span class="font-bold text-xl text-grey">Data:</span> <span>2020.01.12</span>
</div>
<div class="w-1/5">
<span class="text-xl">Zgłoszone przez aplikację</span>
</div>
</div>
</div>
I want replace my img by img from json, "Lipiec 2020 (#123)" => gasmeters.settlement_date (# gasmeters.id), "Stan: " 2120 => Stan: gasmeters.value
How can I make it?
This: {{ gasmeters }} return me:
[ [ { "id": 1, "value": "99.00", "settlement_date": "2020-10-20T22:00:00.000000Z", "loaded_from": "Stan pobrany z systemu BAŁTYKGAZ", "img": "img/icons/crm.svg", "created_at": "2020-10-21T15:09:22.000000Z" }, { "id": 2, "value": "109.00", "settlement_date": "2020-10-20T22:00:00.000000Z", "loaded_from": "Zgłoszone przez aplikację", "img": "img/icons/cms.svg", "created_at": "2020-10-21T17:02:18.000000Z" } ] ]
Please help me
I saw Your problem. Because your response data from service API Laravel is the array in array. If you want to get your right data, you can do in 2 way:
You change the front end data when get from service API, like this:
axios.get(route('api.archive.list'))
.then(response => {
this.gasmeters = _.get(response, "data.data[0]", []);
console.log(this.gasmeters);
})
.catch(error => {
console.log(error);
})
.then(() => {
this.isLoadingInProgress = false;
});
Or you can change the Laravel API like this:
{
"data": [{
"id": 1,
"value": "99.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Stan pobrany z systemu BAŁTYKGAZ",
"img": "img/icons/crm.svg",
"created_at": "2020-10-21T15:09:22.000000Z"
},
{
"id": 2,
"value": "109.00",
"settlement_date": "2020-10-20T22:00:00.000000Z",
"loaded_from": "Zgłoszone przez aplikację",
"img": "img/icons/cms.svg",
"created_at": "2020-10-21T17:02:18.000000Z"
}
]
}
I'm beginner in DataTables or dev in general :)
I use Laravel 5.4 and several DataTables which get their data using ajax calls requests and everything it's working just fine :) .
One of the tables have a column with a hyperlink on it I need to send further in the hyperlink an external variable which is not returned by Ajax response but it's hidden in same form with the table.
So, I have the table definition:
$('#tabelClientiOferta').DataTable({
lengthMenu: [[15, 25, 100, -1], [15,25, 100, "All"]],
processing: true,
serverSide: true,
ajax: 'ajaxClienti',
columns: [
{data:'id',name:'id' , sClass: "hidden", "bSearchable": false },
{data: 'denumire', name: 'denumire',
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
$(nTd).html("<a href='selectieFurnizor?idClient=" + oData.id + "'>" + oData.denumire + "</a>")
}
},
{ data: 'cui', name: 'cui' },
{ data: 'telefon', name: 'telefon', "bSearchable": false},
{ data: 'email', name: 'email', "bSearchable": false },
]
});
Controller function which respond to ajax call:
public function clienti(Request $request)
{
return Datatables::of(DB::table('clienti')->get(['id','denumire','cui','telefon','email']))->make(true);
}
HTML template with table and hidden variable:
#extends ('master')
#section('content')
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="tabelOferte" style ="width: 900px">
<table id = "tabelClientiOferta" class="table table-responsive table-striped table-hover">
<thead >
<tr style="font-weight: bold" >
<td>id</td>
<td>Denumire</td>
<td>CUI</td>
<td>Telefon</td>
<td>Email</td>
</tr>
</thead>
</table>
</div>
<input id = "hiddenId" name="hiddenId" type="text" value = {{$someId}} hidden />
</div>
</div>
</div>
#stop
So I need to pass the hidden variable as the second parameter to the "denumire" column hyperlink, something like:
$(nTd).html("<a href='selectieFurnizor?idClient=" + oData.id + "&hiddenId="+$('#hiddenId') "'>" + oData.denumire + "</a>")
.
Is that possible?
The solution which I use now is to return a view from the controller and include in it a static DataTable (with data already prepared and sent by the controller).
Thank you for your attention
:)
Server-side: use add coloumn from controller
$data = DB::table('clienti')->get(['id','denumire','cui','telefon','email']);
return Datatables::of($data)
->addColumn('clear', function ($data) {
return '<i class="glyphicon glyphicon-trash"></i> Clear';
})
->escapeColumns([])
->make(true);
And add to columns with initial js of datatables
{data: 'clear', name: 'cleat', orderable: false, searchable: false }
or use js based columns render() function, official doc and examples here: https://datatables.net/reference/option/columns.render
I'm using datatable following this example https://datatables.net/examples/data_sources/server_side.html
So my table is:
<table cellpadding="0" cellspacing="0" border="0" class="display" id="tabellaGlossario">
<thead>
<th>
<td>Voce</td>
<td>Sinonimi</td>
<td>Sigla</td>
<td>Macrosettore</td>
<td>Microsettore</td>
<td>Sinonimi</td>
<td>Sigla</td>
<td>Macrosettore</td>
<td>Microsettore</td>
</th>
</thead>
<tfoot>
<th>
<td>Voce</td>
<td>Sinonimi</td>
<td>Sigla</td>
<td>Macrosettore</td>
<td>Microsettore</td>
<td>Sinonimi</td>
<td>Sigla</td>
<td>Macrosettore</td>
<td>Microsettore</td>
</th>
</tfoot>
</table>
My js:
oTable = $('#tabellaGlossario').dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"sDom": '<""f>t<"F"lp>',
"processing": true,
"serverSide": true,
"ajax": "Modules/Glossario/View/Glossario.Table.View.php?lingua_select=2",
});
My ajax returned:
{
"draw": 1,
"recordsTotal": 1,
"recordsFiltered": 1,
"data": [
[
"1",
"2",
"1",
"1",
"1",
"Parola italiana",
"Sinonimo italiano",
"Sigla ita",
"Note ita"
]
]
}
My problem is that i always get "No data available in table" as table results. But as you can see ajax has some results (1 in this example).
It seems my code is the same as the one in official example.
Can't understand why data are not showed in table (and i get no error in browser console).
Are you using some dynamic loading or any kind of routing?
For example angularjs ngroute or some framework's.
In that case it can't work (not as you're doing). You can follow some guide like this or example like this http://jsfiddle.net/qu4a7j24/3/
<div ng-app='testTableApp'>
<div class="container">
<div ng-controller="mainTable">
<form action="" method="POST" class="form-horizontal" role="form">
<div class="form-group">
<legend>Filters</legend>
</div>
<div class="form-group">
<div class="col-sm-10 col-sm-offset-2">
<input type="text" value="0" ng-change='reloadData()' ng-model="start">
<input type="text" value="50" ng-change='reloadData()' ng-model="end">
</div>
</div>
</form>
<table datatable="" dt-options="dtOptions" dt-columns="dtColumns" class="table table-striped table-bordered"></table>
</div>
</div>
</div>
var testTableApp = angular.module( 'testTableApp', ['ngRoute', 'ngResource', 'datatables', 'datatables.tabletools', 'datatables.bootstrap', 'datatables.fixedheader'] );
console.log( testTableApp );
testTableApp.controller("mainTable",
[ '$scope', 'DTOptionsBuilder', 'DTColumnBuilder',
function ( $scope, DTOptionsBuilder, DTColumnBuilder){
$scope.dataSource = "http://dt.ishraf.com/ajax.php";
$scope.start = 0;
$scope.end = 5000;
$scope.getDataSource = function(obj,prefix){
var src = $scope.dataSource;
var str = [];
for(var p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push(typeof v == "object" ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
return src + "?" + str.join("&");
}
var dsParams = {
start : $scope.start,
end : $scope.end
}
$scope.dsString = $scope.getDataSource( dsParams );
$scope.buildTable = function(){
return DTOptionsBuilder
.newOptions()
.withOption('ajax', {
// Either you specify the AjaxDataProp here
dataSrc: 'data',
url: $scope.dsString,
type: 'POST'
}).
withOption( 'lengthMenu', [
[10, 20, 50, 100, 150, 300, 500],
[10, 20, 50, 100, 150, 300, 500]
])
.withTableTools('bower_components/datatables-tabletools/swf/copy_csv_xls_pdf.swf')
.withTableToolsButtons([
{
"sExtends": "copy",
"sButtonText": "<i class='fa fa-copy'></i> | Copy",
"fnInit": function (nButton, oConfig) {
$(nButton).addClass('btn btn-success');
}
},
{
"sExtends": "print",
"sButtonText": "<i class='fa fa-print'></i> | Print",
"fnInit": function (nButton, oConfig) {
$(nButton).addClass('btn btn-danger');
}
},
{
"sExtends": "csv",
"sButtonText": "<i class='fa fa-file-o'></i> | CSV",
"fnInit": function (nButton, oConfig) {
$(nButton).addClass('btn btn-primary');
}
},
{
"sExtends": "pdf",
"sButtonText": "<i class='fa fa-file-pdf-o'></i> | PDF",
"fnInit": function (nButton, oConfig) {
$(nButton).addClass('btn btn-warning');
}
}
])
.withFixedHeader({
bottom: true
})
.withDOM('<"clear"><"#top.hidden-print"<".row"<".col-md-6"i><".col-md-6"f>><".row"<".col-md-6"l><".col-md-6"p>><"clear">T>rt')
;
}
$scope.dtOptions = $scope.buildTable();
$scope.buildColumns = function(){
return [
DTColumnBuilder.newColumn('id').withTitle('ID'),
DTColumnBuilder.newColumn('firstName').withTitle('First name'),
DTColumnBuilder.newColumn('lastName').withTitle('Last name'),
DTColumnBuilder.newColumn('city').withTitle('city'),
DTColumnBuilder.newColumn('state').withTitle('state'),
DTColumnBuilder.newColumn('zip').withTitle('zip'),
DTColumnBuilder.newColumn('country').withTitle('country'),
DTColumnBuilder.newColumn('phone').withTitle('phone'),
DTColumnBuilder.newColumn('email').withTitle('email')
];
}
$scope.dtColumns = $scope.buildColumns();
$scope.reloadData = reloadData;
$scope.dtInstance = {};
function reloadData() {
var resetPaging = false;
$scope.dtInstance.reloadData(callback, resetPaging);
}
function callback(json) {
console.log(json);
}
}
]);
or just dynamic create the table (.load jquery can be useful)
I am building a CRUD application which runs on Data-tables server-side processing, I managed to generate the table dynamically but when I try to create a click-able button for viewing more information, it fails and only shows the unique identifier.
Please advise what am I not doing correctly at the mRenderProp?
Below is my script that generates the data-table :
<script type="text/javascript">
$(document).ready(function () {
Draw();
function Draw() {
$('#example_ta').dataTable({
"bJQueryUI": true,
"bautoWidth": false,
"aoColumns": [
{"sTitle": "Delivery Date", "mDataProp": "delivery_date"},
{"sTitle": "Delivery No.", "mDataProp": "delivery_no"},
{"sTitle": "Unit Code", "mDataProp": "unit_code"},
{"sTitle": "Driver Code.", "mDataProp": "driver_code"},
{"sTitle": "Zone Name.", "mDataProp": "zone_name"},
{"sTitle": "Zone Rate", "mDataProp": "zone_rate"},
{"sTitle": "Tonnage", "mDataProp": "tonnage"},
{"sTitle": "Standard Tonne", "mDataProp": "standard_tonne"},
{"sTitle": "View", "mDataProp": "delivery_id",
"mRenderProp": function (data, type, full) {
return '<button class="show-data btn btn-small btn-primary" id = ' + data + ' >View</button>';
}
},
],
"bDeferRender": true,
"bProcessing": true,
"bDestroy": true,
"bLengthChange": true,
"iDisplayLength": 10,
"sAjaxDataProp": "",
"sAjaxSource": '<?php echo site_url() . "admin_profile/getDeliveries/"; ?>',
"aaSorting": [[3, "asc"]]
});
}
});
</script>
<table class="example_ta" id="example_ta">
<thead>
<tr>
</tr>
</thead>
<tbody>
<tr></tr>
</tbody>
</table>
It's just mRender not mRenderProp - see docs
{"sTitle": "View", "mDataProp": "delivery_id",
"mRender": function (data, type, full) {
return '<button class="show-data btn btn-small btn-primary" id = ' + data + ' >View</button>';
}
I have a datatable that I'm using in server-side mode to retrieve data via AJAX. On the surface everything appears correct however, when I load the page I get "No Matching Records Found" displayed instead of the data displaying. The peculiar part is that it says it is showing the records "Showing records 1 to 2 of 2 entries".
The table HTML and JS is as follows:
<div class="container">
<script type="text/javascript">
$(document).ready(function() {
$("#freebieslist").dataTable({
"bServerSide": true,
"sAjaxSource": "/config/getadvertisers",
"bPaginate": true,
"bProcessing": true,
"bFilter" : true,
"sPaginationType" : "bootstrap",
"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>"
});
$.extend( $.fn.dataTableExt.oStdClasses, {
"sWrapper": "dataTables_wrapper form-inline"
} );
});
</script>
<div class="row"><h1 class="pull-left">Advertisers</h1><div class="pull-right" style="margin-top:15px;">Add New Delete</div> </div>
<div class="row">
<div class="span12">
<table id="freebieslist" class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th class="span1"> </th><th>Advertiser</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div> </div>
The JSON being loaded is this:
{
"sEcho": "1",
"iTotalRecords": "2",
"iTotalDisplayRecords": "2",
"aaData": [
[
"2",
"Test2"
],
[
"1",
"Tester"
]
]
}
How to fix this so it actually displays the returned rows?
I solved the issue by using datatables debugger in Chrome. I checked the AJAX result coming back (based on the get paramaters datatables was passing in) and found it was getting a null result set. A quick change in the server side code and things started working properly.