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

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();
}

Related

Laravel 9 Livewire get Datatable from DB using Ajax request

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

A non well formed numeric value encountered when creating a custom Yajra Datatable

I am using Laravel and I want to create a custom server side Yajra Datatable.
My Ajax call is below:
let table = $('#myTable').DataTable({
"bLengthChange": false,
"iDisplayLength": 20,
"info": false,
processing: true,
serverSide: true,
ajax: {
url: "/myURL",
dataSrc: '',
data: function (d) {
d.start = '2020-04-01';
d.end = '2020-07-20';
d.table = true;
},
},
columns: [
{data: 'name', name: 'name'},
{data: 'nameMerged', name: 'nameMerged'},
{data: 'count', name: 'count'},
],
});
$("#myTable").append('<tfoot><tr><th>' + 'Total:' + '</th><th></th><th>'
+ total + '</th></tr></tfoot>');
The controller for the ajax call is getting an array from another function that looks like (tableObject) and transforms the array into a Datatable.
DataTable transform function:
public function transformTable($start, $end)
{
$tableObject = $this->getTableData($start, $end);
return DataTables::of($tableObject['datasets'])
->addIndexColumn()
->addColumn('name', function ($row) {
return $row->name;
})
->addColumn('nameMerged', function ($row) {
return $row->nameMerged;
})
->addColumn('count', function ($row) {
return $row->count;
})
->setRowClass(function ($data) {
return 'tr-basic';
})
->with('total', $tableObject['total'])
->make(true);
}
Table in Blade file:
<div>
<h2>Employees:</h2>
<table id="myTable" class="bravo-list">
<thead>
<tr>
<th class="th-toggler"></th>
<th class="th-fullname" id="th-employee">Mitarbeiter</th>
<th class="th-fullname" id="th-count"># Bravos</th>
</tr>
</thead>
</table>
</div>
This, however, returns the following error:
A non well formed numeric value encountered
The error occurs beacause the variables "start" and "end" in the ajax call are reserved keywords. I changed the name of the variables and it works now as aspected.

Vue / Laravel - Dynamic multiple form saving data

I have a dynamic form that successfully adds multiple field by a click of the button. My problem comes when saving the data in the database. I want to be able to save in the employee_id field the id of the Auth::user.
This is my current set of code. Should I use a different approach such as for loop instead of foreach?
Component.vue
<tr v-for="(row, index) in rows" :key="row.id">
<td><base-select
:items="department_objectives"
item-text="department_objective"
item-value="id"
label="Department Objectives"
/></td>
<td><v-textarea label="KPA" placeholder=" " class="mr-2" rows="1" outlined v-model="row.kpa" /></td>
<td><v-textarea label="KPI" placeholder=" " class="mr-2" rows="1" outlined v-model="row.kpi" /></td>
<td><v-text-field label="Weight" placeholder=" " class="mr-2" outlined v-model="row.weight" /></td>
<td><v-text-field label="Score" placeholder=" " class="mr-2" outlined :disabled="disabled" filled v-model="row.score" /></td>
<td><a #click="removeElement(index);" style="cursor: pointer">Remove</a></td>
</tr>
addRow () {
this.rows.push({
kpa: '',
kpi: '',
weight: '',
score: '',
equal: '',
});
save () {
axios
.post('/api/employee-objective', { data: this.rows })
.then(res => { console.log(res) })
.catch(err => { console.log(err) });
}
Controller.php
public function store(Request $request) {
foreach($request->data as $data) {
$container = EmployeeObjective::updateOrCreate([
'employee_id' => // insert ID
'kpa_info' => $data['kpa'],
'kpi_info' => $data['kpi'],
'kpa_weight' => $data['weight'],
'kpa_score_1' => $data['score'],
'kpa_equal' => $data['equal'],
]);
$container->save();
}
}
It's fine using foreach as long all data you want is available like the key
to put the id of authenticated user in employee_id just put this one
Auth::id();
and put it above your code
use Auth;
I managed to make it work, somehow this syntax works. Hopefully someone could enlighten me more about this.
Controller.php
public function store(Request $request)
// This works
foreach($request->rows as $data) {
$test = new EmployeeObjective;
$test->employee_id = $request->id;
$test->kpa_info = $data['kpa'];
$test->save();
// This does not work
foreach($request->rows as $data) {
EmployeeObjective::updateOrCreate([
'employee_id' => $request->id,
'kpa_info' => $data['kpa'],
Now here is the tricky part. I saved the data from the $store to my local object and passed it during the save method.
Component.vue
created () {
this.auth = this.$store.state.authUser.id
},
save () {
axios.post('/api/employee-objective', {
rows: this.rows,
id: this.auth
})
.then(res => { console.log(res) })
.catch(err => { console.log(err) });
}

How to show specific Category based on choose of selection of dropdown

I have categories table and clubs table, relationship between is
A category has many clubs
1 category can have many clubs
1 club have 1 category
I want to show clubs based on category, which will be selected with dropdown list, so other clubs will be hided. See the Screenshot for more understanding
My Controller (I have no issues getting category names to dropdown list):
public function club()
{
$categories_name = Category::pluck('category_name','id');
$user_id = auth()->user()->id;
$user = User::find($user_id);
$data = array(
'user_clubs' => $user->clubs,
'categories_name' => $categories_name
);
return view('pages.dashboard.club_dashboard')->with($data);
}
My View
<div class="form-group">
<strong>{{Form::label('categories_name', 'Select Category')}}</strong>
{{Form::select('categories_name', $categories_name, null, ['class' => 'form-control'], array('name'=>'categories_name[]'))}}
</div>
#if (count($user_clubs)>0)
<table class="table table-striped">
<tr>
<th><strong>Club Name</strong></th>
<th></th>
<th></th>
</tr>
#foreach ($user_clubs as $club)
<tr>
<th>{{$club->club_name}} | {{$club->category->category_name}} </th>
<td>Edit</td>
<td>
{!!Form::open(['action' => ['ClubsController#destroy', $club->id], 'method' => 'POST', 'class' => 'float-right'])!!}
{{Form::hidden('_method','DELETE')}}
{{Form::submit('Delete', ['class' => 'btn btn-danger'])}}
{!!Form::close()!!}
</td>
</tr>
#endforeach
</table>
#else
<p>You Have No posts</p>
#endif
3.Category Model
class Category extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function clubs(){
return $this->hasMany('App\Club');
}
}
4.Club Model
class Club extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function category(){
return $this->belongsTo('App\Category');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js>">
onchange alert($("#categories_name").length);
console.log($("#categories_name").length);
$(document).ready(function(){
$("#categories_name").on("change", function(){
var category_id = $(this).val();
$("table tr").each(function(index){
if (index != 0) {
$row = $(this);
if ($row.attr('id')!=category_id) {
$row.hide();
}
else {
$row.show();
}
}
});
});
});​
</script>
I wrote this script from answer below it still not working please, help me find where did I make mistake? where should I put the script?
//add category id to your tr's
#foreach ($user_clubs as $club)
<tr id="{{$club)->category->id}}">
//Rest of your code
</tr>
#endforeach
//Your jquery
$("#categories_name").on("change", function() {
var category_id = $(this).val();
$("table tr").each(function(index) {
if (index != 0) {
$row = $(this);
if ($row.attr('id')!=category_id) {
$row.hide();
}
else {
$row.show();
}
}
});
});​

Error 405: Method not allowed, EditUser route can't get info

So I've been learning Laravel and was getting into making DataTables. However, my 'editItem' route is not being able to get any information when I click 'Edit' button. It shows Error 405.
DataTable view (dt.blade.php) -
HTML part where the table is displayed
<div class="table-responsive text-center">
<table class="table table-borderless" id="table">
<thead>
<tr>
<th class="text-center">ID</th>
<th class="text-center">Name</th>
<th class="text-center">Created At</th>
<th class="text-center">Updated At</th>
<th class="text-center">Actions</th>
</tr>
</thead>
#foreach($users as $user)
<tr class="user{{$user->id}}">
<td >{{$user->id}}</td>
<td>{{$user->name}}</td>
<td>{{$user->created_at}}</td>
<td>{{$user->updated_at}}</td>
<td><button class="edit-modal btn btn-info"
value="{{$user->id}},{{$user->name}}">
<span class="glyphicon glyphicon-edit"></span> Edit
</button>
<button class="delete-modal btn btn-danger"
value="{{$user->id}},{{$user->name}}">
<span class="glyphicon glyphicon-trash"></span> Delete
</button></td>
</tr>
#endforeach
</table>
</div>
JS part in the same file
<script>
$(document).ready(function() {
$('#table').DataTable();
} );
</script>
<script>
$(document).on('click', '.edit-modal', function() {
$('#footer_action_button').text("Update");
$('#footer_action_button').addClass('glyphicon-check');
$('#footer_action_button').removeClass('glyphicon-trash');
$('.actionBtn').addClass('btn-success');
$('.actionBtn').removeClass('btn-danger');
$('.actionBtn').removeClass('delete');
$('.actionBtn').addClass('edit');
$('.modal-title').text('Edit');
$('.deleteContent').hide();
$('.form-horizontal').show();
var stuff = $(this).val().split(',');
console.log($(this).val());
fillmodaluser(stuff)
$('#myModal').modal('show');
});
$(document).on('click', '.delete-modal', function() {
$('#footer_action_button').text(" Delete");
$('#footer_action_button').removeClass('glyphicon-check');
$('#footer_action_button').addClass('glyphicon-trash');
$('.actionBtn').removeClass('btn-success');
$('.actionBtn').addClass('btn-danger');
$('.actionBtn').removeClass('edit');
$('.actionBtn').addClass('delete');
$('.modal-title').text('Delete');
$('.deleteContent').show();
$('.form-horizontal').hide();
var stuff = $(this).val().split(',');
console.log($(this).val('info'));
$('.did').text(stuff[0]);
$('.dname').html(stuff[1]);
$('#myModal').modal('show');
});
function fillmodaluser(details){
$('#fid').val(details[0]);
$('#name').val(details[1]);
}
$('.modal-footer').on('click', '.edit', function() {
$.ajax({
type: 'post',
url: '../public/editUser',
user: {
'_token': $('input[name=_token]').val(),
'id': $('#fid').val(),
'name': $('#name').val()
},
success: function(user) {
if (user.errors){
$('#myModal').modal('show');
if(user.errors.name) {
$('.name_error').removeClass('hidden');
$('.name_error').text("Name can't be empty !");
}
if(user.errors.email) {
$('.email_error').removeClass('hidden');
$('.email_error').text("Email must be a valid one !");
}
}
else {
$('.error').addClass('hidden');
$('.user' + users.id).replaceWith("<tr class='users" + users.id + "'><td>" +users.id + "</td><td>" + users.name+"</td><td>" + "</td><td>" + "</td><td><button class='edit-modal btn btn-info' user-info='" + users.id+","+users.name+"'><span class='glyphicon glyphicon-edit'></span> Edit</button> <button class='delete-modal btn btn-danger' user-info='" + users.id+","+users.name+"' ><span class='glyphicon glyphicon-trash'></span> Delete</button></td></tr>");
}}
});
});
$('.modal-footer').on('click', '.delete', function() {
$.ajax({
type: 'post',
url: '../public/deleteUser',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
user: {
'_token': $('input[name=_token]').val(),
'id': $('.did').text()
},
success: function(user) {
$('.user' + $('.did').text()).remove();
}
});
});
</script>
And lastly, the web.php
Route::get('/dt', 'UserController#dt');
Route::get('/editUser', function (Request $request) {
$rules = array (
'name' => 'required|alpha',
);
$validator = Validator::make(Input::all(), $rules );
if ($validator->fails ())
return Response::json ( array (
'errors' => $validator->getMessageBag()->toArray ()
) );
else {
$user->id = User::find ( $request->id );
$user->name = ($request->name);
$user->save ();
return response ()->json ( $user );
}
});
Route::get ('/deleteUser', function (Request $request) {
User::find ( $request->id )->delete ();
return response ()->json ();
});
The JSON error that shows to me is "{"errors":{"name":["The name field is required."]}}"
My question is that, the info can be split fine in the JQuery here when I press the Edit button; it is able to show the info of the row I've selected. I don't understand why the same values aren't getting sent to my editUser route?
change all get method to post , because you are using post in client side
Route::post('/dt', 'UserController#dt');
Route::post('/editUser', function (Request $request) {
$rules = array (
'name' => 'required|alpha',
);
$validator = Validator::make(Input::all(), $rules );
if ($validator->fails ())
return Response::json ( array (
'errors' => $validator->getMessageBag()->toArray ()
) );
else {
$user->id = User::find ( $request->id );
$user->name = ($request->name);
$user->save ();
return response ()->json ( $user );
}
});
Route::post ('/deleteUser', function (Request $request) {
User::find ( $request->id )->delete ();
return response ()->json ();
});
Seems your urls should not be '../public/' (in your ajax requests) but it should match what you typed in your file web.php

Resources