I want to know how to display multiple images that is stored in the database as an array : ["img1.jpeg","img2.png"]
Here is my controller.
In my case only one image is displayed in the datatable.
if ($request->ajax()) {
$data = Actualite::latest()->get();
return Datatables::of($data)
->addIndexColumn()
->editColumn('created_at', function ($data) {
return $data->created_at->format('Y-m-d'); // human readable format
})
->addColumn('image', function ($data) {
$images = json_decode($data->image);
if ((is_array($images) || is_object($images))) {
$imgs="";
foreach ($images as $image ) {
$url= asset('storage/actualite/'.$image);
$imgs = '<img src="'.$url.'" width="30" class="img-fluid rounded-circle" alt="" />' ;
}
}
return $imgs;
})
->addColumn('action', function ($data) {
$btns ='<div class="btn-group">
<button type="button" class="btn btn-dark btn-sm">Action</button>
<button type="button" class="btn btn-dark btn-sm dropdown-toggle dropdown-toggle-split" id="dropdownMenuReference1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-reference="parent">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuReference1">
<a class="dropdown-item" href="actualités/edit/'.$data->id.'" class="edit">Edit</a>
<a class="dropdown-item" onclick="return confirm(`Êtes-vous sûr de supprimer cet enregistrement ?`)" href="actualités/destroy/'.$data->id.'">Delete</a>
</div>
</div>';
return $btns;
})
->rawColumns(['image','action'])
->make(true);
}
i assume you are only getting only last image as output as this is not an array variable
$imgs="";
Related
I'm working on a Review module in laravel that can sort from All Ratings, Like, and Dislike. However, I'd also like to display the count of All Reviews, likes, and dislikes. Below is my code for the dropdown as well as the model.
Review Dropdown
#props(['routeName', 'username'])
<div class="flex items-center">
<span class="text-sm text-gray-700 uppercase m-1">{{ __('Review:') }}</span>
<div class="relative" x-data="{ open: false }" #click.outside="open = false" #close.stop="open = false">
<div #click="open = ! open">
<button class="flex items-center text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out">
<div>{{ App\Models\Review::RATING[request()->rating] ?? __('All') }}</div>
<div class="ml-1">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>
</div>
</button>
</div>
<div x-show="open" class="absolute z-50 mt-2 w-20 rounded-md shadow-lg" style="display: none;" #click="open = false"> {{-- origin-top-right right-0 --}}
<div class="rounded-md ring-1 ring-black ring-opacity-5 py-1 bg-white overflow-y-auto py-1 h-30">
<x-dropdown-link href="{{ route($routeName, [$username]) }}?{{ http_build_query(request()->except('rating', 'page')) }}">
{{ __('All') }}
</x-dropdown-link>
#foreach(App\Models\Review::RATING as $value => $label)
<x-dropdown-link href="{{ route($routeName, [$username]) }}?rating={{ $value }}&{{ http_build_query(request()->except('rating', 'page')) }}">
{{ __($label) }}
</x-dropdown-link>
#endforeach
</div>
</div>
</div>
</div>
ReviewModel
class Review extends Model
{
use HasFactory;
protected $table = 'reviews';
protected $fillable = [
'customer_username',
'customer_id',
'business_id',
'rating',
'feedback'
];
const RATING = [
'1' => 'Dislike',
'2' => 'Like'
];
public function scopeFilter($query, $rating){
$query->when($rating ?? false, function ($query, $rating) {
$query->where(function ($query) use ($rating) {
$query->where('rating', $rating);
});
});
}
}
This is what I intend it to look like:
I did try adding ::count() and ->count() on App\Models\Review::RATING after the foreach in the dropdown but it broke the application.
What am i not doing right? i'm woking on a livewire project that needs to get the grade_id's to show in show-component.blade.php, from Modules table which is related to a Grades table. My challenge is that, it only show a particular id, like the one in the mount section, so if i change it to 2 it will only show id's that are 2's, though thats really what i wanted but i can be change it manually.
use App\Models\Grade;
use App\Models\Module;
use Livewire\Component;
class ShowComponent extends Component
{
public $modules;
public $grades;
public function mount()
{
$this->modules = Module::all()->where("grade_id", "1");
}
public function render()
{
return view('livewire.show-component');
}
}
=========================================================================
show-component.blade.php
#foreach($modules as $module)
<div class="flex flex-col grid-cols-12 md:grid text-gray-50">
<div class="flex md:contents">
<div class="relative col-start-2 col-end-4 mr-10 md:mx-auto">
<div class="flex items-center justify-center w-6 h-full">
<div class="w-1 h-full bg-green-500 pointer-events-none"></div>
</div>
<div class="absolute w-6 h-6 -mt-3 text-center bg-green-500 rounded-full shadow top-1/2">
<i class="text-white fas fa-check-circle"></i>
</div>
</div>
<div class="w-full col-start-4 col-end-12 p-4 my-4 mr-auto bg-green-500 shadow-md rounded-xl">
<h2 class="mb-1 text-lg font-semibold">
{{ $module->name }}
</h2>
<p class="w-full leading-tight text-justify">
<a href="{{ url('storage/videos'.$module->video) }}">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</svg>
</a>
</p>
</div>
</div>
</div>
#endforeach
==================================================================
Module's Model
public function grade()
{
return $this->belongsTo(Grade::class, 'grade_id', 'id');
}
===============================================================
Grade's Model
public function curricula()
{
return $this->belongsTo(Curriculum::class, 'curricula_id', 'id');
}
public function module()
{
return $this->hasMany(Module::class);
}
If you want all Module records stored in your database table, you want to remove the where condition which is limiting the return value.
$this->modules = Module::all();
If you want just the grade_ids from your modules table, use pluck:
$grade_ids = Module::pluck('grade_id');
I think what you want is ..
Add
public $grade_id;
Then in mount
$this->modules = Module::where("grade_id", $this->grade_id)->get();
When you load your component you can pass grade_id to it
I am running into a very strange issue where I have a chatroom that should update whenever a new message is posted. Instead when I add a new message the x-data is getting updated and I can see the message there but the x-for doesnt seem to run and it never appears on the frontend. Then when I enter another message the previous message shows up on the frontend but the latest message does not show even though the x-data has been updated to reflect it.
Here is the code below:
<div
x-data="{{ json_encode(['messages' => $messages, 'messageBody' => '']) }}"
x-init="
Echo.join('chat.2')
.listen('ChatSent', (e) => {
#this.call('incomingMessage', e)
console.log(e)
})
">
<div
class="wow fadeInUp mb-10 rounded-md bg-light-bg dark:bg-dark"
data-wow-delay="0s"
>
<h3
class="border-b border-body-color border-opacity-10 py-4 px-8 text-lg font-semibold text-black dark:border-white dark:border-opacity-10 dark:text-white"
>
Chat
</h3>
<div id="chat-window" class="relative w-full p-3 overflow-y-auto h-[14rem]">
<ul class="space-y-2">
<template
x-for="message in messages"
:key="message.id"
>
<div>
<template x-if="message.user_id == {{ Auth::user()->id }}">
<li class="flex justify-end">
<div class="relative max-w-xl px-4 py-2 text-black dark:text-white bg-gray-100 dark:bg-black rounded shadow">
<span class="block" x-text="message.body"></span>
</div>
</li>
</template>
<template x-if="message.user_id != {{ Auth::user()->id }}">
<li class="flex justify-start">
<div class="relative max-w-xl px-4 py-2 text-black dark:text-white bg-blue-100 dark:bg-[#1e2a78] rounded shadow">
<span class="block" x-text="message.body"></span>
</div>
</li>
</template>
</div>
</template>
</ul>
</div>
<div class="flex items-center justify-between w-full p-3 border-t border-gray-300">
<input
#keydown.enter="
#this.call('sendMessage', messageBody)
messageBody = ''
"
x-model="messageBody"
type="text"
placeholder="Message"
class="block w-full py-2 pl-4 mx-3 bg-gray-100 dark:bg-black rounded-full outline-none focus:text-gray-700 dark:focus:text-white dark:text-white"
name="message" required />
<button
#click="
#this.call('sendMessage', messageBody)
messageBody = ''
">
<svg class="w-5 h-5 text-black dark:text-white origin-center transform rotate-90" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" fill="currentColor">
<path
d="M10.894 2.553a1 1 0 00-1.788 0l-7 14a1 1 0 001.169 1.409l5-1.429A1 1 0 009 15.571V11a1 1 0 112 0v4.571a1 1 0 00.725.962l5 1.428a1 1 0 001.17-1.408l-7-14z" />
</svg>
</button>
</div>
#error('messageBody')
<div class="w-full p-2 text-center">
<span class="text-red-500">Message is required!</span>
</div>
#enderror
</div>
<div
class="wow fadeInUp mb-10 rounded-md bg-light-bg dark:bg-dark"
data-wow-delay="0s">
<h3
class="border-b border-body-color border-opacity-10 py-4 px-8 text-lg font-semibold text-black dark:border-white dark:border-opacity-10 dark:text-white"
>
Active Players
</h3>
<ul class="flex flex-wrap py-6 px-8">
#forelse($here as $authData)
<li>
<a
href="javascript:void(0)"
class="text-body-color-3 mr-3 mb-3 inline-flex items-center justify-center rounded-full border-[.5px] border-body-color bg-body-color bg-opacity-10 py-2 px-4 hover:border-primary hover:bg-primary hover:text-white dark:border-[#363D68] dark:bg-[#272E5C] dark:text-white dark:hover:border-primary dark:hover:bg-primary dark:hover:text-white"
>
{{ $authData['name'] }}
</a>
</li>
#empty
#endforelse
</ul>
</div>
</div>
I figure it has to be something simple I am missing and hopefully someone can point me in the right direction.
EDIT to include Livewire code:
<?php
namespace App\Http\Livewire;
use App\Events\ChatSent;
use App\Models\Chat;
use App\Models\Games;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class Chatbox extends Component
{
public $game_id, $game, $chats;
public $here = [];
public $messages = [];
public function getListeners()
{
$game_id = $this->game_id;
return [
"echo-presence:chat.{$game_id},here" => 'here',
"echo-presence:chat.{$game_id},joining" => 'joining',
"echo-presence:chat.{$game_id},leaving" => 'leaving',
];
}
public function render()
{
return view('games.components.chatbox');
}
public function mount()
{
$this->game = Games::find($this->game_id);
$this->messages = Chat::
where('games_id', $this->game_id)
->with('user')
->latest()
->limit(30)
->get()
->reverse()
->values()
->toArray();
}
public function sendMessage($body)
{
if (! $body) {
$this->addError('messageBody', 'Message body is required.');
return;
}
$message = Auth::user()->chats()->create([
'body' => $body,
'games_id' => $this->game_id,
]);
$message->load('user');
broadcast(new ChatSent($message, $this->game))->toOthers();
$myMessage = $message->toArray();
$this->dispatchBrowserEvent('update-chat');
array_push($this->messages, $myMessage);
}
/**
* #param $message
*/
public function incomingMessage($message)
{
// get the hydrated model from incoming json/array.
$message = Chat::with('user')->find($message['id']);
array_push($this->messages, $message);
$this->dispatchBrowserEvent('update-chat');
}
/**
* #param $data
*/
public function here($data)
{
$this->here = $data;
}
/**
* #param $data
*/
public function leaving($data)
{
$here = collect($this->here);
$firstIndex = $here->search(function ($authData) use ($data) {
return $authData['id'] == $data['id'];
});
$here->splice($firstIndex, 1);
$this->here = $here->toArray();
}
/**
* #param $data
*/
public function joining($data)
{
$this->here[] = $data;
}
}
I'm using DataTables in Laravel and putting dynamic data into it with ajax. When I fetch the data from MySQL it works but when I fetch it from Elasticsearch it returns an ajax error.
DataTables warning: table id=htmkl5-extension - Ajax error. For more information about this error, please see http://datatables.net/tn/7
This the controller function :
if ($request->ajax()) {
$rawdata = Autorisation::searchByQuery(array('match' =>
array('nom_autorisation' => 'Autorisation')));
$data = new \Illuminate\Database\Eloquent\Collection($rawdata);
return DataTables::of($data)
->addIndexColumn()
->addColumn('action', function ($data) {
$btns ='<div class="btn-group">
<button type="button" class="btn btn-dark btn-sm">Open</button>
<button type="button" class="btn btn-dark btn-sm dropdown-toggle dropdown-toggle-split" id="dropdownMenuReference1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-reference="parent">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuReference1">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="admin/users/'.$data->id.'" class="edit">Edit</a>
<a class="dropdown-item" href="users/destroy/'.$data->id.'">Delete</a>
</div>
</div>';
return $btns;
})
->rawColumns(['action'])
->make(true);
}
This is the script :
<script>
$('#html5-extension').DataTable( {
processing:true,
serverSide:true,
ajax:{
url:"{{route('autorisation')}}",
},
columns:[
{
data: 'num_decret', name: 'num_decret'
} ,
{
data: 'nom_autorisation', name: 'nom_autorisation'
},
{
data: 'ministere_competent', name: 'ministere_competent'
},
{
data: 'action', name: 'action',
orderable:true,
searchable:true
}
]
});
<script>
We are currently building a chat for the application with livewire. There is an issue, when no chats are selected the last message shows but when selecting a chat. The last messages are gone. And I have no idea why. SQL queries look the same...
code, livewire component:
class Inbox extends Component
{
public ?Collection $chats = null;
public ?User $selectedUser = null;
public ?Collection $selectedChat = null;
public string $newMessage = '';
public function mount()
{
$this->chats = Auth::user()->getChats();
}
public function selectChat(int $userId)
{
$this->selectedUser = User::find($userId);
$this->selectedChat = Auth::user()->getChatWith($this->selectedUser);
$this->newMessage = '';
$this->dispatchBrowserEvent('scroll-to-bottom');
}
public function unselectChat()
{
$this->selectedUser = null;
$this->selectedChat = null;
$this->newMessage = '';
}
public function send()
{
if (empty($this->newMessage)) {
return;
}
$this->selectedChat->push(
Message::from(Auth::user())
->to($this->selectedUser)
->send($this->newMessage)
);
$this->newMessage = '';
$this->dispatchBrowserEvent('scroll-to-bottom');
}
public function render()
{
return view('livewire.inbox', [
'chats' => Auth::user()->getChats(),
]);
}
}
traits
trait HasMessages
{
public function lastMessage()
{
return $this->belongsTo(Message::class);
}
public function scopeWithLastMessage(Builder $query, int $id)
{
return $query->addSelect([
'last_message_id' => Message::select('id')
->where(
fn ($q) => $q->where('sender_id', $id)->whereColumn('receiver_id', 'users.id')
)->orWhere(
fn ($q) => $q->where('receiver_id', $id)->whereColumn('sender_id', 'users.id')
)
->latest('created_at')->latest('id')
->take(1)
])->whereExists(
fn ($q) => $q->select('id')
->from('messages')
->where(
fn ($q) => $q->where('sender_id', $id)->whereColumn('receiver_id', 'users.id')
)->orWhere(
fn ($q) => $q->where('receiver_id', $id)->whereColumn('sender_id', 'users.id')
)
)->with('lastMessage');
}
public function getChats()
{
return User::query()
->withLastMessage($this->id)
->where('id', '<>', $this->id)
->get()
->sortBy([
['lastMessage.created_at', 'desc'],
['lastMessage.id', 'desc'],
]);
}
public function getChatWith(User $user)
{
return Message::where(
fn ($q) => $q->where('sender_id', $this->id)->where('receiver_id', $user->id)
)->orWhere(
fn ($q) => $q->where('receiver_id', $this->id)->where('sender_id', $user->id)
)->oldest('created_at')->oldest('id')
->with(['sender', 'receiver'])
->get();
}
}
the view, inbox chat blade:
<div {{ $attributes->merge(['class' => 'flex items-center px-4 sm:px-6 py-3 bg-white hover:bg-gray-100 cursor-pointer transition']) }}>
<img src="{{ $chat->profilePhotoUrl }}"
class="flex-shirink-0 w-10 h-10 rounded-full" />
<div class="flex-1 ml-4 mr-2 min-w-0">
<h5 class="text-gray-700 font-bold truncate">
{{ $chat->name }}
</h5>
<p class="text-gray-500 text-sm truncate---">
{{-- {{ $chat->lastMessage->body }} --}}
lastMessage: {{ $chat->lastMessage }}
</p>
</div>
{{-- <time class="text-gray-500 text-xs"
datetime="{{ $chat->lastMessage->created_at }}">
{{ $chat->lastMessage->created_at->diffForHumans() }}
</time> --}}
</div>
inbox chat header
#props(['user', 'clickHandler'])
<div class="flex items-center px-4 sm:px-6 py-3 bg-white border-t border-gray-200 shadow-lg">
<button class="md:hidden -ml-2 p-2 rounded-lg text-gray-500 hover:bg-gray-100 transition"
wire:click.prevent="{{ $clickHandler }}">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>
</button>
<img src="{{ $user->profilePhotoUrl }}"
class="ml-2 flex-shirink-0 w-10 h-10 rounded-full" />
<div class="flex-1 ml-4 mr-2 min-w-0">
<h5 class="text-gray-700 font-bold">
{{ $user->name }}
</h5>
</div>
</div>