Laravel 9 Livewire get Datatable from DB using Ajax request - ajax

with laravel controller the app working without anz problem,like that:
UserController.php
public function user_list(Request $request)
{
if ($request->ajax()) {
$data = User::whereHas('roles')->get()->map(function($permission) {
return [
'id' => $permission->id,
'fullname' => $permission->name . ', ' . $permission->lastname,
];
});
return datatables()->of($data)->make(true);
}
$pageConfigs = ['pageHeader' => false];
return view('/content/apps/user/app-user-list', ['pageConfigs' => $pageConfigs]);
}
in my view :
<div class="card">
<div class="table-responsive">
<table class="users-table table">
<thead class="table-light">
<tr>
<th>id</th>
<th>Full Name</th>
</tr>
</thead>
</table>
</div>
</div>
#section('page-script')
<script>
$(function() {
$('.users-table').DataTable({
ajax: "list", // JSON file to add data
columns: [
// columns according to JSON
{ data: "id" },
{ data: "fullname" },
</script>
#endsection
and the route in Web.php is:
Route::get('users', [UsersController::class, 'user_list'])->name('list');
now when i want to use Livewire component instead of Laravel controller , where should i du my request in 'render' function or in 'mount' or schould i create another function, and how can i call if from route. or if there someway to call the function direct from controller without creating a new function on more time in Livewire component.
will be greate when someone can helpe

Related

How to display subnested arrays in Vue search component - Laravel

I'm having issues displaying eloquent relationship data via my vue.js search template, specifically my customer->biller fields.
models.student_first_name will display however
models.billers.biller_first_name wont show anything
The search function is working on my customers.index view using the following
CustomerDetailsController:
public function getData(Request $request){
$search = $request->search;
$customer = Customer::with('orders', 'billers', 'paymentplans', 'paidinfulls')->where(DB::raw('concat(student_first_name," ",student_last_name)'), 'like', '%'.$search.'%')->paginate(20);
return response()->json([
'model' => $customer
]);
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$customers = Customer::with('orders', 'paymentplans', 'billers')->orderBy('created_at', 'desc')->where('owner', Auth::user()->name)->paginate(25);
return view('customers.index', compact('customers', 'orders', 'paymentplans', 'funding'));
}
Customers.vue:
<template>
<div class="container">
<div class="field m-b-20">
<p class="control has-icons-left">
<input #keyup="fetchDataCustomer()" type="text" class="form-control input" name="search" v-model="search" placeholder="Search">
<span class="icon is-small is-left"><i class="fa fa-search"></i></span>
</p>
</div>
<table class="table">
<thead>
<tr>
<th>Student Name</th>
<th>Email</th>
<th>Biller Name</th>
<th>Biller Email</th>
<th>Courses Purchased</th>
<th>Deposit</th>
<th>Payment Plan</th>
<th>Accepted</th>
<th>Receipted</th>
</tr>
</thead>
<tbody>
<tr v-for="models in model.data">
<td>{{models.student_first_name}} {{models.student_last_name}}</td>
<td>{{models.student_email}}</td>
<td>{{models.billers.biller_first_name}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import axios from 'axios'
export default{
data(){
return {
model: {},
search:'',
url:'api/customers'
}
},
created:function (){
this.fetchDataCustomer()
},
methods: {
fetchDataCustomer(){
var vm = this
axios.get(`${this.url}?search=${this.search}`)
.then(function (response) {
Vue.set(vm.$data, 'model', response.data.model)
})
}
}
}
</script>
JSON output of a search result
{"model":{"current_page":1,"data":[{"id":"627d0130-4dd0-11e8-91dd-69869f509337","enrolment_id":"John","student_first_name":"John","student_last_name":"Smith","student_email":"johnsmith#mail.com","address":"123 Test Street","suburb":"Townsville","postcode":"9999","state":"AAA","home_phone":null,"work_phone":null,"mobile_phone":"0444444444","dob":"1999-01-01 00:00:00","drivers_license_number":"123738974987498","owner":"Sales Man","owner_email":"salesman#business.com","created_at":"2018-05-02 16:16:43","updated_at":"2018-05-02 16:16:43","orders":[{"id":933,"fc_account":16,"customer_id":"627d0130-4dd0-11e8-91dd-69869f509337","biller_id":246,"enrolment_id":"John","course_id":5,"delivery_mode":0,"course_cost":"2000.00","deposit":null,"gov_funding":"0","location":"0","Monday":0,"Tuesday":0,"Wednesday":0,"Thursday":0,"Friday":0,"Saturday":0,"Sunday":0,"start_time":null,"end_time":null,"start_date":null,"enrolment_issue_date":"2018-05-02","sale_type":2,"created_at":"2018-05-02 16:17:24","updated_at":"2018-05-02 16:17:24"}],"billers":[{"id":246,"customer_id":"627d0130-4dd0-11e8-91dd-69869f509337","biller_first_name":"John","biller_last_name":"Smith","biller_email":"johnsmith#mail.com","biller_address":null,"biller_suburb":null,"biller_postcode":null,"biller_state":null,"biller_phone":null,"created_at":"2018-05-02 16:17:24","updated_at":"2018-05-02 16:17:24"}],"paymentplans":[{"id":"836e7e40-4dd0-11e8-a907-83f96c25a7d0","enrolment_id":"John","customer_id":"627d0130-4dd0-11e8-91dd-69869f509337","paysmart_id":"FIT69869f509337","biller_id":246,"biller_first_name":"John","biller_last_name":"Smith","biller_email":"johnsmith#mail.com","payment_method":-1,"contract_value":"1500.00","interest_free":1,"payment_frequency":1,"commencement_date":"2018-05-24 00:00:00","payment":"100.00","first_payment":"200.00","admin_fee":"1.30","setup_fee":"5.50","deposit":"500.00","deposit_payment_method":"Cash","special_conditions":null,"accepted":null,"accepted_student":null,"created_at":"2018-05-02 16:17:38","updated_at":"2018-05-02 16:17:38","submitted":1,"biller_ip":null,"student_ip":null}],"paidinfulls":[]}]
Vue Debug
Your models.billers is an array but you're treating it as an object. So you'll have to access it via models.billers[0].biller_first_name instead of models.billers.biller_first_name given that it is always available.

Update paginator laravel in ajax

I create a page on which there is a table with a paginator. I post a request to specify the output of rows from the database for insertion into the table. However, the paginator remains old. How should I change it?
Get a request for a new page or insert all the HTML code that comes from the controller is not satisfied.
Code view:
<table class="table table-bordered text-center table-hover" id="table_list">
<thead>
<tr>
<th>id</th>
</tr>
<tr>
<td><input type="text" class="form-control" id="id_card" value=""></td>
</tr>
</thead>
<tbody>
#if($dats)
#foreach($dats as $data)
<tr>
<td><div class="help" data-id="{{ $data['id'] }}"> {{$data['id']}}</div></td>
</tr>
#endforeach
#endif
</tbody>
</table>
{{ $dats->links() }} // After completing the ajax, the link remains old and allows you to navigate through the old table
Js code in view:
$('#id_card').on('keyup', function(){ // search
value = $(this).val();
$.ajax({
type: 'POST',
url: '/home',
data: {
search: value,
code: 1,
_token: '{{csrf_token()}}'
},
success: function (data) {
$('#table_list').empty();
$('#table_list').append(data); // update table
//update paginator links
},
error: function(data){
console.log(data);
}
})
})
Code controller
public function search(Request $request){
$models= Model::where('table','LIKE','%'.$request->input('search').'%')->paginate(4);
$str = "";
foreach($models as $model){
$str .= '<tr>'.
'<td>'. $model["id"].'</td>'.
'</tr>';
}
print($str);
return;
}
In Laravel 5, you could do it by changing your controller to something like this.
public function search(Request $request){
$models= Model::where('table','LIKE','%'.$request->input('search').'%')->paginate(4);
$str = "";
foreach($models as $model){
$str .= '<tr>'.
'<td>'. $model["id"].'</td>'.
'</tr>';
}
return response()->json([
'rows' => $str,
'links' => $models->render()
], 200);
}
In your ajax response, render the links with $('ul.pagination').replaceWith(data.links);
eg.
$.ajax({
type: 'POST',
url: '/home',
data: {
search: value,
code: 1,
_token: '{{csrf_token()}}',
page: page
},
success: function (data) {
$('#table_list').empty();
$('#table_list').append(data.rows); // update table
$('ul.pagination').replaceWith(data.links); // update links
},
error: function(data){
console.log(data);
}
});

Laravel + Datatables, how to pass id to the controller?

I want to start using Datatables on my Laravel project, so I have followed this tutorial: https://youtu.be/ejj-078OvfY
It works well, but I can't figure it out how to pass a parameter to my controller since that route is being called by an AJAX call through a JavaScript function on the view.
It may sound a bit weird if you are not familiarized with the tutorial, so let me show you how this is setup:
ROUTE:
Route::get('/client/{id}', array('before' => 'auth', 'as' => 'getClient', 'uses' => 'ClientsController#getClient'));
Route::get('getAllParticipants', array('before' => 'auth', 'as' => 'getAllParticipants', 'uses' => 'ClientsController#showAllParticipants'));
CONTROLLER:
public function getClient() {
return View::make('/forms/dashboard_clients');
}
public function showAllParticipants () {
$allParticipants = User::where('users.id', '=', $id) //I need the ID parameter here
->join('users_roles', 'users.id', '=', 'users_roles.user_id')
->where('users_roles.role_id', '!=', Role::USER_PARTICIPANT)
->groupBy('users.id')
->get();
return Datatable::collection($allParticipants)
->searchColumns('firstname', 'lastname', 'email')
->orderColumns('firstname', 'lastname', 'email')
->addColumn('firstname', function ($model) {
return $model->firstname;
})
->addColumn('lastname', function ($model) {
return $model->lastname;
})
->addColumn('email', function ($model) {
return $model->email;
})
->make();
}
VIEW:
<div class="row">
<div class="col-md-12">
<table id="allParticipants" class="table table-striped table-hover">
<thead>
<tr>
<th scope="col">#lang('table.headers.fname')</th>
<th scope="col">#lang('table.headers.lname')</th>
<th scope="col">#lang('table.headers.email')</th>
<th scope="col">#lang('table.headers.action')</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
var allParticipants=null;
$(document).ready(function(){
allParticipants = $('#allParticipants').dataTable({
"ajax": "/getAllParticipants",
"lengthMenu": [[10, 50, 100, -1], [10, 50, 100, "All"]]
});
});
</script>
So to summarize, the user lands into the /client/{id} route where the view gets printed. From that view, the JavaScript identifies the table by its id and it sends an Ajax call that triggers the getAllParticipants route where a collection of participants gets sent to the view.
Any idea on how can I specify an ID parameter to that showAllParticipants function on my controller?
From what i can see you want to be able to set an ID parameter on a route, that's simple enough, the question is how Datatables makes that AJAX request, does it send an ID when it makes the "getAllParticipants" call?
If so you can go about it in two ways, either you set an ID on that route like you did for the client route. Or you use a traditional GET parameter and fetch it by calling $request->input('paramname') in your controller.
What confuses me is that your Datatable is not sending any data it's just calling the Controller route without sending any data.
To send data it should i believe look like this
$('#example').dataTable( {
"ajax": {
"url": "/getAllParticipants",
"data": {
"id": 451
}
}
} );
or alternatively
$('#example').dataTable( {
"ajax": {
"url": "/getAllParticipants?id=" + 451
}
} );
This way in my controller i would inject the Request class and get the "id" from that
public function showAllParticipants (Request $request) {
$id = $request->input('id');
$allParticipants = User::where('users.id', '=', $id) //I need the ID parameter here
->join('users_roles', 'users.id', '=', 'users_roles.user_id')
->where('users_roles.role_id', '!=', Role::USER_PARTICIPANT)
->groupBy('users.id')
->get();
return Datatable::collection($allParticipants)
->searchColumns('firstname', 'lastname', 'email')
->orderColumns('firstname', 'lastname', 'email')
->addColumn('firstname', function ($model) {
return $model->firstname;
})
->addColumn('lastname', function ($model) {
return $model->lastname;
})
->addColumn('email', function ($model) {
return $model->email;
})
->make();
}

Sorting and Filtering ajax data using Laravel and VueJs

Current code is sorting and filtering data using vue.js. It is working fine but data is dummy, it is hardcoded. I need to get data dynamically from table using vue js and laravel. How can I get dynamic data in gridData?
JS
Vue.component('demo-grid', {
template: '#grid-template',
props: {
data: Array,
columns: Array,
filterKey: String
},
data: function () {
var sortOrders = {}
this.columns.forEach(function (key) {
sortOrders[key] = 1
})
return {
sortKey: '',
sortOrders: sortOrders
}
},
methods: {
sortBy: function (key) {
this.sortKey = key
this.sortOrders[key] = this.sortOrders[key] * -1
}
}
})
// bootstrap the demo
var demo = new Vue({
el: '#app',
data: {
searchQuery: '',
gridColumns: ['name', 'power'],
gridData: [
{ name: 'Chuck Norris', power: Infinity },
{ name: 'Bruce Lee', power: 9000 },
{ name: 'Jackie Chan', power: 7000 },
{ name: 'Jet Li', power: 8000 }
]
}
})
laravel.blade.php
#extends('layouts.app')
#section('title', 'Customers List')
#section('styles')
#endsection
#section('content')
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading">Customers List</div>
<div class="panel-body">
<script type="text/x-template" id="grid-template">
<table class="table table-hover table-bordered">
<thead>
<tr>
<th v-for="key in columns" #click="sortBy(key)" :class="{active: sortKey == key}">#{{key | capitalize}}<span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'"></span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="entry in data | filterBy filterKey | orderBy sortKey sortOrders[sortKey]">
<td v-for="key in columns">
#{{entry[key]}}
</td>
</tr>
</tbody>
</table>
</script>
<div id="app">
<form id="search">
Search <input name="query" v-model="searchQuery">
</form>
<demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery"></demo-grid>
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
#section('scripts')
<script src="/js/vue.js"></script>
<script src="/js/vue-resource.min.js"></script>
<script src="/js/customers.js"></script>
#endsection
You will need to do a few things.
First, in Laravel, create a new route in your routes.php file, for ex.:
Route::get('/api/fighters', 'SomeController#index');
Then in your controller (somecontroller.php), you will have a method index which will query your database table and return it as JSON data.
public function index() {
//query your database any way you like. ex:
$fighters = Fighter::all();
//assuming here that $fighters will be a collection or an array of fighters with their names and power
//when you just return this, Laravel will automatically send it out as JSON.
return $fighters;
}
Now, in Vue, your can call this route and grab the data. Using AJAX. You can use any AJAX library that you like, even jQuery. I currently use Superagent.js. Vue will work just fine with any.
So, in your Vue code, create a new method to get your data.:
methods: {
getDataFromLaravel: function() {
//assign `this` to a new variable. we will use it to access vue's data properties and methods inside our ajax callback
var self = this;
//build your ajax call here. for example with superagent.js
request.get('/api/fighters')
.end(function(err,response) {
if (response.ok) {
self.gridData = response.body;
}
else {
alert('Oh no! We have a problem!');
}
}
}
}
Then you can just call this new method using a button or anyway you like. For example, using a button click event:
<button type="button" #click="getDataFromLaravel">Get Data</button>
Or you can even just have the data loaded automatically using Vue's ready function:
// bootstrap the demo
var demo = new Vue({
el: '#app',
data: {
.... }
ready: function () {
this.getDataFromLaravel();
},
methods: {
.... }
});
Done! You now have your database data assigned to Vue's data property gridData.

Laravel Datatables 1 => active / 0 => not active

I'm using Laravel Framework and yajrabox datatables.
I have a table of users with 2 columns , a status column and a type of account column. Both of these holds ints.
How can I change these ints to strings? How can I perform an db request on the values of the $users variable in the cntroller?
Also is it possible to concat 2 columns into 1? So first_name and last_name into 1 column?
My current setup :
userlist.blade.php
#extends('app')
#section('content')
<div class='portlet light bordered '>
<div class='portlet-title'>
<div class='caption font-red-sunglo'>
Ledenbeheer
</div>
<div class="actions">
<a id='create' href="javascript:;" class="btn btn-circle red-sunglo">
Nieuw lid </a>
<a id='excel_import' href="javascript:;" class="btn btn-circle btn-default">
<i class="fa fa-fax"></i>Excel import </a>
</div>
</div>
<div class='portlet-body'>
<table class="table table-bordered table-striped table-hover" id="users-table">
<thead>
<tr>
<th>Naam</th>
<th>Email</th>
<th>Status</th>
<th>Account type</th>
<th>Created At</th>
<th>Updated At</th>
</tr>
</thead>
</table>
</div>
</div>
#stop
#push('scripts')
<script>
$(function() {
$('#users-table').DataTable({
processing: true,
serverSide: true,
ajax: '{!! route('configuratie_leden.data') !!}',
});
});
</script>
#endpush
UserController.php
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use yajra\Datatables\Facades\Datatables;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
//
public function getIndex(){
$users = User::all();
return view('users.userlist');
}
public function anyData(){
$users = User::select(['first_name','email','status','account_type','created_at','updated_at']);
return Datatables::of($users)->make();
}
}
Routes :
// Routes module configuratie
Route::controller('configuratie_leden','UserController',
[
'getIndex' => 'configuratie_leden',
'anyData' => 'configuratie_leden.data'
]);
Javascript solution:
columns: [
{
data: 'status',
name: 'status',
render: function ( data, type, full, meta ) {
return data ? "active" : "not active" ;
}
}
]
That's how you can change int to string. When data is 1, it will print "active".
Also is it possible to concat 2 columns into 1? So first_name and last_name into 1 column?
Yes it is. You do it in your query.
$users = User::select([
DB::raw("CONCAT(users.name,'-',users.surname) as name_surname"),
'email',
'created_at',
'updated_at'
]);
Example: http://datatables.yajrabox.com/eloquent/post-column-search
For column types, you can define attribute casts in your User model class
class User extends Model
{
protected $casts = [
'status' => 'string',
'account_type' => 'string',
];
protected $appends = ['full_name'];
public function getFullNameAttribute()
{
return $this->first_name . ' ' . $this->last_name;
}
}

Resources