laravel-admin
laravel-admin copied to clipboard
Model popup using AJAX to show current contents and icon change
- Laravel Version: 9
- PHP Version: 8.0.9
- Laravel-admin: 1.8.17
Description:
I am using Grid Column Model to load Related Notes, but unfortunately it has 2 issues
- Icon for Column is always Clone icon, there is no way to change it
- All popup data is loaded with page load, how to load it using AJAX on Icon click, so latest records can be shown.
Steps To Reproduce:
`$grid->column('notes', __('Notes'))->display(function ($title, $column) { $notes = $this->notes()->with('admin:id,name')->take(10)->orderBy('id','desc')->get()->map(function ($note) { //return $note->only(['id','description','admin_user_id' , 'created_at']); return [$note->id,nl2br($note->description ."\n\r\n\rBy ".$note->admin->name ." @ ".date("d/m/Y h:i A",strtotime($note->created_at)))]; }); // dd($notes->flatten()->toArray()); // Otherwise it is displayed as editable if(count($notes)>0){ //Show Icon, and show Notes in model popup if count greater than 0 return $column->modal('Latest Notes', function ($column) use($notes) { return new Table(['ID', 'Description'], $notes->toArray(),['table-striped']); //return new Box('No Information', 'There is no note to show'); });
}else{
return "-";//Donot show Icon
}
});`
Was curious about this too and here's what I've found. $grid->column('files')->model($title, $callback = null);
accepts two arguments, and the $callback one can be an actual \Closure that returns a string/Renderable (as in the docs' example), or a name of the class that implements \Illuminate\Contracts\Support\Renderable.
In the last case, no render will be called during the Grid render, but ajax load using admin.handle-renderable
will be made on the icon click.
It will pass to your Renderable the "key" (primaryKey / id) of the current row, and everything else is just similar to what you do in the callback with tiny adjustments.
For example:
class PostFilesRenderable implements \Illuminate\Contracts\Support\Renderable {
public function render() {
$files = File::query()->select(['id', 'path'])->where('post_id', request('key'))->get()->map(function($item) {
$item->size = file_size(\Illuminate\Support\Facades\Storage::disk('admin')->size($item->path));
return $item;
});
$table = new \Encore\Admin\Widgets\Table(['ID', 'Path', 'Size'], $files->toArray());
return $table->render() . "<h4>Total files: " . $files->count() . "</h4>";
}
}
Your controller's grid:
$grid->column('files')->model('Files', PostFilesRenderable);
As to "fa-clone" icon change - it's hardcoded into resources/views/components/column-modal.blade.php
. But you can override this view if you really need it, as described here.
In your app/Admin/bootstrap.php
:
app('view')->prependNamespace('admin', resource_path('views/vendor/laravel-admin'));
You need to follow the same dir structure, so for admin::components.column-modal
(from Encore\Admin\Grid\Displayers\Modal@display
) you need to create file in views/vendor/laravel-admin/components.column-modal
with the same content as in original + your modifications.
Example of the first 3 lines edited:
@if ($value == 0)
<span data-toggle="modal" data-target="#grid-modal-{{ $name }}" data-key="{{ $key }}">
<a href="javascript:void(0)"><i class="fa fa-eye"></i> {{ $value }}</a>
</span>
@else
<span> --- </span>
@endif
OR you can just simply don't display anything for the column if you don't want to, depending on the original value:
$grid->column('files')->model('Files', PostFilesRenderable)
->display(function (string $c, Grid\Column $column) {
return $column->getOriginal() ? $c : '---';
});
Hi @alexoleynik0 thanks for these directions, it help me in achieving goal. I was busy, when you suggest. Today i spare time to implement it.
but there are a couple of things that i face, so i wants to share, it may help others.
1. $grid->column('files')->model('Files', PostFilesRenderable);
here model should be modal
2. modal accept class i.e. instead of PostFilesRenderable we have to write PostFilesRenderable:class
regarding icon instead of copying view i use the struct you provided to control display
$grid->column('files')->model('Files', PostFilesRenderable)
->display(function (string $c, Grid\Column $column) {
return $column->getOriginal() ? $c : '---';
});
in my case for notes i also count notes available as notes_count, as follow
$grid->column('notes_count', __('Notes'))->modal(__('Notes'),ShowNote::class)
->display(function (string $c, Grid\Column $column) {
if($column->getOriginal()==0){ //if notes_count is 0
return '-';
}
return str_replace('fa-clone','fa-eye',$c); //replace icon with your icon of choice
});
Thank you for your help.