Using a modal to delete a user - laravel

I'm trying to create a modal that when you click delete it will delete a record, but first I need to be able to have
that modal pop up.
I know that the reason is because of this line $('#delete_{{ $user->id }}').click(function(){ but I'm not sure how to add the user id without having to add the <script>...</script> to the foreach loop
Or do I need to do that?
Here is my code
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Name
</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider text-right">
Add User
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
#foreach($users as $user)
<tr>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="flex items-center">
<div class="ml-4">
<div class="text-sm leading-5 font-medium text-gray-900">
{{ $user->name }}
</div>
<div class="text-sm leading-5 text-gray-500">
{{ $user->email }}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap text-right text-sm leading-5 font-medium">
<button id="delete_{{ $user->id }}" class="bg-red-400 hover:bg-red-300 text-red-800 font-bold py-2 px-4 rounded inline-flex items-center">
Delete
</button>
</td>
</tr>
#endforeach
</tbody>
</table>
<div class="modal-display-none">
<div class="fixed z-10 inset-0 overflow-y-auto">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen"></span>​
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-headline">
Delete User
</h3>
<div class="mt-2">
<p class="text-sm leading-5 text-gray-500">
Are you sure you want to delete this user? <br>
This action cannot be undone.
</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<span class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
<form action="{{ route('users.delete', ['user' => $user->id]) }}" method="POST">
#method('DELETE')
#csrf
<button type="button"
class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-red-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-red-500 focus:outline-none focus:border-red-700 focus:shadow-outline-red transition ease-in-out duration-150 sm:text-sm sm:leading-5"
id="confirm_delete"
>
Delete
</button>
</form>
</span>
<span class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto">
<button type="button" id="close" class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-base leading-6 font-medium text-gray-700 shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 sm:text-sm sm:leading-5">
Cancel
</button>
</span>
</div>
</div>
</div>
</div>
</div>
<style>
.modal-display-none{
display: none;
}
.modal-display{
display: block;
}
</style>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(document).ready(function(){
$('#delete_{{ $user->id }}').click(function(){
console.log('delete button');
$('.modal-display-none').removeClass('modal-display-none').addClass('modal-display');
});
$('#confirm_delete').click(function(){
$('.modal-display').removeClass('modal-display').addClass('modal-display-none');
});
$('#close').click(function(){
$('.modal-display').removeClass('modal-display').addClass('modal-display-none');
});
});
</script>

replace your syntax (inside foreach)
<button id="delete_{{ $user->id }}" class="bg-red-400 hover:bg-red-300 text-red-800 font-bold py-2 px-4 rounded inline-flex items-center">Delete</button>
replace with this syntax bellow, it will show an alert to confirm the Delete action
{!! Form::open(['route' => ['users.delete', $user->id], 'method' => 'delete']) !!}
{!! Form::button('<i class="fa fa-trash"></i>', [
'type' => 'submit',
'class' => 'bg-red-400 hover:bg-red-300 text-red-800 font-bold py-2 px-4 rounded inline-flex items-center',
'onclick' => "return confirm('Are you sure want to delete this item?')"
]) !!}
{!! Form::close() !!}

Related

How to pass data between components Laravel

Hello I'm confused on how should I pass collections/data to another component so I can display it in another component (in this case I'm showing discounts so it will be a section with popular discounts and another section showing latest discounts).
So i have this index.blade.php and i'm a bit confused on how to pass the data to x-discount-card component so I can access to $discount->title on the component. Right now I get "undefined variable $discount" so it seems i'm not accessing it right.
<x-layout>
<main>
#include('components.categories-row')
#include('discounts._best')
<section class="w-4/6 mx-auto my-8 font-bold flex flex-col items-center justify-center">
<h1 class="uppercase text-main-gray text-4xl bold self-start text-center mb-4 ">Últimos Descuentos</h1>
#if($discounts->count())
#foreach($discounts as $discount)
<x-discount-card :discount="$discount" />
#endforeach
#else
<p class="my-8 text-center">No hay descuentos disponibles. Por favor vuelva mas tarde. </p>
#endif
</section>
</main>
</x-layout>
discount-component
#props(['discount'])
<div
class="w-[20rem] h-auto bg-gradient-to-b from-card-light-gray to-card-main-gray p-6 rounded-2xl drop-shadow-xl md:w-[35rem] lg:w-[35rem] lg:w-[50rem] lg:h-auto mb-4">
<div class="flex-col items-center text-center justify-center h-full lg:grid lg:grid-cols-4 lg:grid-rows-4">
<a href="" class="flex justify-center lg:row-span-4 lg:-ml-10">
<img class="h-full " src="/images/pngwing.com.png" alt="" width="120" height="120">
</a>
<div
class="flex-col justify-center items-center text-center w-full lg:col-start-2 lg:col-span-full lg:row-start-1 lg:row-span-full lg:-ml-14">
<a href="/discount/1" class="lg:grid lg:row-start-2">
<h2 class="text-white font-bold text-lg md:text-2xl lg:my-2">{{ $discount->title }}</h2>
<div class="flex my-4 items-center text-center justify-center lg:my-2">
<p class="text-price-color font-bold mr-8 text-xl md:text-2xl">139,99€</p>
<p class="line-through text-white text-lg md:text-lg">149,99 (-10€)</p>
</div>
<p class="text-white my-8 text-sm md:text-lg lg:my-4">Bambas nike con 10€ de descuento y envio gratis.
Salen a
139,99€</p>
</a>
<div
class="flex-col items-center justify-center gap-2 lg:flex-row lg:inline-flex lg:col-start-2 lg:col-span-full lg:row-start-4 lg:row-end-5">
<a class="flex items-center justify-center my-2 " href="/user/1">
<img class="rounded-full mr-2" src="https://i.pravatar.cc/35"
alt="">
<p class="mr-4 text-white text-sm font-bold transition-transform hover:translate-x-0.5 md:text-lg">
JohnDoe</p>
</a>
<div class="flex items-center justify-center my-4 gap-4 lg:mx-4">
<div
class="border border-light-gray p-1 rounded-md transition-transform hover:-translate-y-0.5 cursor-pointer">
<img class="h-full" src="/images/heart.png" alt="" width="22" height="22">
</div>
<div
class="border border-light-gray p-1 rounded-md transition-transform hover:-translate-y-0.5 cursor-pointer">
<img class="h-full" src="/images/dislike.png" alt="" width="22" height="22">
</div>
<div
class="flex items-center border border-light-gray p-1 rounded-md transition-transform hover:-translate-y-0.5 cursor-pointer lg:px-4">
<img class="h-full" src="/images/comment.png" alt="" width="22" height="22">
<p class="text-light-gray ml-2">10</p>
</div>
</div>
<div class="flex justify-center lg:w-[250px] lg:-mr-14">
<button
class="flex my-4 items-center justify-center bg-gradient-to-b from-button-light-orange to-button-dark-orange p-2 rounded-md transition-transform hover:-translate-y-0.5 md:p-4 lg:w-full ">
<p class="text-light-gray mr-4 font-bold text-sm md:text-lg ">Ver Chollo</p>
<img src="/images/external-link.png" alt="" width="20" height="20">
</button>
</div>
</div>
</div>
</div>
<div
class="w-auto absolute top-5 left-5 flex-col items-center justify-center rounded-2xl bg-button-light-orange p-2 drop-shadow-lg md:flex-row md:inline-flex">
<p class="text-white text-xs uppercase font-bold mr-2 md:text-sm ">10%</p>
<p class="text-white text-xs uppercase font-bold md:text-sm ">descuento</p>
</div>
</div>
Also on the routes file i'm passing discounts but i'm a bit confused on how should I pass the data because right now i'm getting "undefined variable $discount error"
Route::get('/', function () {
return view('discounts.index', [
'discounts' => Discount::all(),
// ->where('premium','=',false)
'categories' => Category::all()
]);
})->name('home');
On the discounts._best component i'll display the discounts with more likes but this will be done in the future but I share the component too because maybe something there is what is causing the error.
<section class=" w-full text-center h-3/4 bg-light-gray flex flex-col items-center justify-center p-10">
<h1 class="uppercase text-main-gray mb-8 text-4xl font-bold">Descuentos Populares</h1>
<x-discount-card />
</section>
I searched on the Laravel Documentation about Component attributes but I dont know what i'm doing wrong and still confused.

Laravel Blade For each loop alternate display

I want to present my blade view in a nice way.
First id, it will show the image on the left, and the content on the right.
Second id, it will show the image on the right, and the content on the left. But I'm not sure how to loop this., 3rd id it will again show image on the left, and content on the right, and so on and so forth.
Anybody can help? Thanks
#foreach ($users as $user)
<div class="box-border flex flex-col items-center content-center px-8 mx-auto leading-6 text-black border-0 border-gray-300 border-solid md:flex-row max-w-7xl lg:px-16">
<!-- Image on the left-->
<div class="box-border relative w-full max-w-md px-4 mt-5 mb-4 -ml-5 text-center bg-no-repeat bg-contain border-solid md:ml-0 md:mt-0 md:max-w-none lg:mb-0 md:w-1/2 xl:pl-10">
<img src="{{$user->image}}" class="p-2 pl-6 pr-5 xl:pl-16 xl:pr-20 ">
</div>
<!-- Content on the right-->
<div class="box-border order-first w-full text-black border-solid md:w-1/2 md:pl-10 md:order-none">
<h2 class="m-0 text-xl font-semibold leading-tight border-0 border-gray-300 lg:text-3xl md:text-2xl">
{{$user->title}}
</h2>
<p class="pt-4 pb-8 m-0 leading-7 text-gray-700 border-0 border-gray-300 sm:pr-12 xl:pr-32 lg:text-lg">
{{$user->body}}
</p>
<ul class="p-0 m-0 leading-6 border-0 border-gray-300">
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_1}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
</ul>
</div>
<!-- End Content -->
</div>
<div class="box-border flex flex-col items-center content-center px-8 mx-auto mt-2 leading-6 text-black border-0 border-gray-300 border-solid md:mt-20 xl:mt-0 md:flex-row max-w-7xl lg:px-16">
<!-- Content on left-->
<div class="box-border w-full text-black border-solid md:w-1/2 md:pl-6 xl:pl-32">
<h2 class="m-0 text-xl font-semibold leading-tight border-0 border-gray-300 lg:text-3xl md:text-2xl">
{{$user->title}}
</h2>
<p class="pt-4 pb-8 m-0 leading-7 text-gray-700 border-0 border-gray-300 sm:pr-10 lg:text-lg">
{{$user->body}}
</p>
<ul class="p-0 m-0 leading-6 border-0 border-gray-300">
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_1}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
</ul>
</div>
<!-- End Content -->
<!-- Image on the right-->
<div class="box-border relative w-full max-w-md px-4 mt-10 mb-4 text-center bg-no-repeat bg-contain border-solid md:mt-0 md:max-w-none lg:mb-0 md:w-1/2">
<img src="{{$user->image}}" class="pl-4 sm:pr-10 xl:pl-10 lg:pr-32">
</div>
</div>
#endforeach
Inside of a blade loop you have access to the $loop variable which you can use to check if the current index is odd or even.
#foreach ($users as $user)
#if($loop->even)
{{-- The index is event --}}
#else
{{-- The index is odd --}}
#endif
#endforeach
or
#foreach ($users as $user)
#if($loop->odd)
{{-- The index is odd --}}
#else
{{-- The index is even --}}
#endif
#endforeach
It's easier than you think. You just have to use a variable that you may only access inside a #foreach that is $loop. This variable comes with many helpful properties you can read on here but the ones you need are $loop->even and $loop->odd. Coupled with the ternary operator to make a condition inside the class and tailwind's ability to reorder items, this should be easily manageable without having to duplicate any code.
#foreach($users as $user)
<div class="{{$loop->odd ? "order-first" : "order-last"}}">image</div>
<div class="{{$loop->even ? "order-first" : "order-last"}}">content</div>
#endforeach()
You can use condition in loop.
Like:
if($key % 2 == 0){
// show right image and left content part
} else {
// show left image and right content part
}
Updated file:
#foreach ($users as $key => $user)
#if($key % 2 == 0)
<div class="box-border flex flex-col items-center content-center px-8 mx-auto mt-2 leading-6 text-black border-0 border-gray-300 border-solid md:mt-20 xl:mt-0 md:flex-row max-w-7xl lg:px-16">
<!-- Content on left-->
<div class="box-border w-full text-black border-solid md:w-1/2 md:pl-6 xl:pl-32">
<h2 class="m-0 text-xl font-semibold leading-tight border-0 border-gray-300 lg:text-3xl md:text-2xl">
{{$user->title}}
</h2>
<p class="pt-4 pb-8 m-0 leading-7 text-gray-700 border-0 border-gray-300 sm:pr-10 lg:text-lg">
{{$user->body}}
</p>
<ul class="p-0 m-0 leading-6 border-0 border-gray-300">
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_1}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
</ul>
</div>
<!-- End Content -->
<!-- Image on the right-->
<div class="box-border relative w-full max-w-md px-4 mt-10 mb-4 text-center bg-no-repeat bg-contain border-solid md:mt-0 md:max-w-none lg:mb-0 md:w-1/2">
<img src="{{$user->image}}" class="pl-4 sm:pr-10 xl:pl-10 lg:pr-32">
</div>
</div>
#else
<div class="box-border flex flex-col items-center content-center px-8 mx-auto leading-6 text-black border-0 border-gray-300 border-solid md:flex-row max-w-7xl lg:px-16">
<!-- Image on the left-->
<div class="box-border relative w-full max-w-md px-4 mt-5 mb-4 -ml-5 text-center bg-no-repeat bg-contain border-solid md:ml-0 md:mt-0 md:max-w-none lg:mb-0 md:w-1/2 xl:pl-10">
<img src="{{$user->image}}" class="p-2 pl-6 pr-5 xl:pl-16 xl:pr-20 ">
</div>
<!-- Content on the right-->
<div class="box-border order-first w-full text-black border-solid md:w-1/2 md:pl-10 md:order-none">
<h2 class="m-0 text-xl font-semibold leading-tight border-0 border-gray-300 lg:text-3xl md:text-2xl">
{{$user->title}}
</h2>
<p class="pt-4 pb-8 m-0 leading-7 text-gray-700 border-0 border-gray-300 sm:pr-12 xl:pr-32 lg:text-lg">
{{$user->body}}
</p>
<ul class="p-0 m-0 leading-6 border-0 border-gray-300">
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_1}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
<li class="box-border relative py-1 pl-0 text-left text-gray-500 border-solid">
<span class="inline-flex items-center justify-center w-6 h-6 mr-2 text-white bg-yellow-300 rounded-full"><span class="text-sm font-bold">✓</span></span> {{$user->sub_2}}
</li>
</ul>
</div>
<!-- End Content -->
</div>
#endforeach

Vue Laravel not showing data from method

I know I am blind because I've been looking at this for 2 days off and on and I think I am just eye stuck on what is really going on. Below is the code. What SHOULD happen is an array of data should be shown into a modal. I can see the data as "rooms" in web inspector with all the fields, but it isnt populating into the v-for - all im asking for is a little help if you can see where I screwed up
<!-- This example requires Tailwind CSS v2.0+ -->
<template>
<TransitionRoot as="template" :show="open">
<Dialog as="div" class="fixed z-10 inset-0 overflow-y-auto" #close="open = false">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
<DialogOverlay class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</TransitionChild>
<!-- This element is to trick the browser into centering the modal contents. -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leave-from="opacity-100 translate-y-0 sm:scale-100" leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div class="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:p-6">
<button type="button" class="bg-white rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" #click="open = false">
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
<span class="sr-only">Close</span>
<XIcon class="h-6 w-6" aria-hidden="true" />
</div>
</button>
<div class="sm:flex sm:items-start">
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Room
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Description
</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Type
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">Enter</span>
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr v-for="room in chatRooms" :key="room.id">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" :src="room.image" alt="" />
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">
{{ room.name }}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">{{ room.description }}</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full" :class="[room.is_private === 'Public' ? 'bg-green-100 text-green-800' : room.is_private === 'Private' ? 'bg-red-100 text-red-800' : '']">
{{ room.is_private }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
Enter
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</TransitionChild>
</div>
</Dialog>
</TransitionRoot>
</template>
<script>
import { ref } from 'vue'
import { Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot } from '#headlessui/vue'
import { ExclamationIcon, XIcon } from '#heroicons/vue/outline'
export default {
props: ['rooms'],
data: function () {
return {
chatRooms: [],
rooms: [],
}
},
methods: {
getRooms() {
axios.get('/chat/rooms')
.then(response => {
this.chatRooms = response.data;
})
.catch(error => {
console.log(error);
})
}
},
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ExclamationIcon,
XIcon,
},
setup() {
const open = ref(true)
return {
open,
}
},
}
</script>
Try this :
Maybe this is the cause of your problem.
Add this piece of code before methods: {} and tell me :
created() {
this.getRooms();
},
The issue was not something anyone here could solve with the information provided. So I am typing this answer in a way that I hope will trigger some help to others.
When you are doing a v-for snippet, it is important to remember what data is being pulled for processing. In my case, the following line was the issue
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full" :class="[room.is_private === 'Public' ? 'bg-green-100 text-green-800' : room.is_private === 'Private' ? 'bg-red-100 text-red-800' : '']">
room.is_private is a boolean not the data I want to visualize. So by saying Public and Private, I was breaking the for statement. By changing them to True and False, I was able to process the v-for statement and actually get the code to load. The solution I used was as follows. Note there are 2 versions of true and false. This is because Postgres and sqlite both expect to see the response differently. I noticed this when it worked local with 'true' but pgsql on the deployment didn't work. So this Is why the code is this way
<div v-if="room.is_private === true" class="rounded-full py-1 px-2 bg-red-100 text-red-800">
<span>Private</span>
</div>
<div v-else-if="room.is_private === false" class="rounded-full py-1 px-2 bg-green-100 text-green-800">
<span>Public</span>
</div>
<div v-else-if="room.is_private === 'true'" class="rounded-full py-1 px-2 bg-red-100 text-red-800">
<span>Private</span>
</div>
<div v-else-if="room.is_private === 'false'" class="rounded-full py-1 px-2 bg-green-100 text-green-800">
<span>Public</span>
</div>
The important lesson here is to make sure you sample the data and fields before running into code making mistakes on the type of data being requested.

Make selected item current

EDIT: Full code for the 3 most likely files are found here.
https://codepen.io/arcticmedia-ryan/project/editor/ZEQwmN
I am not sure how best to explain this so please let me know if you want more. I am building a chat room app. When a person opens up the main vue, they are presented with a "Room List" - from there they can click enter and join the room. The issue is, when they click join, it opens up the tab for the room but doesnt make it active. I feel like I am just banging my head around a simple problem
There is a prop called "SelectedRoomID" that needs to be updated from "undefined" to the room that is selected from the list.
RoomList.vue
<!-- This example requires Tailwind CSS v2.0+ -->
<template>
<TransitionRoot as="template" :show="isOpen">
<Dialog as="div" class="fixed z-10 inset-0 overflow-y-auto" #close="$emit('onClose')">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0"
enter-to="opacity-100" leave="ease-in duration-300" leave-from="opacity-100"
leave-to="opacity-0">
<DialogOverlay class="fixed inset-0 bg-gray-700 bg-opacity-75 transition-opacity"/>
</TransitionChild>
<!-- This element is to trick the browser into centering the modal contents. -->
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<TransitionChild as="template" enter="ease-out duration-300"
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-300"
leave-from="opacity-100 translate-y-0 sm:scale-100"
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div class="inline-block align-bottom bg-black bg-opacity-20 rounded-lg px-6 pt-5 pb-4 text-left overflow-hidden shadow-2xl transform transition-all sm:my-8 sm:align-middle sm:p-6">
<div class="sm:flex sm:items-start">
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="align-middle inline-block min-w-full sm:px-4 lg:px-5">
<div class="shadow overflow-hidden border-8 border-gray-800 dark:border-gray-900 sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-800">
<thead class="bg-gray-800 dark:bg-gray-900">
<tr>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Room
</th>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Description
</th>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Type
</th>
<th scope="col"
class="px-6 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
Users
</th>
<th scope="col" class="relative px-6 py-3">
<button type="button"
class="bg-white rounded-md text-gray-400 hover:text-gray-500 "
#click="$emit('onClose')">
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
<span class="sr-only">Close</span>
<XIcon class="top-1 right-1 absolute h-6 w-6 text-gray-50 " aria-hidden="true"/>
</div>
</button>
<span class="sr-only">Enter</span>
</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-300 dark:divide-gray-600">
<tr v-for="room in $store.state.rooms.rooms" :key="room.id">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" :src="room.image"
alt=""/>
</div>
<div class="ml-4">
<div class="text-md font-medium text-gray-900 dark:text-gray-50">
{{ room.name }}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-md text-gray-900 dark:text-gray-50">{{ room.description }}</div>
</td>
<td class="px-2 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-s leading-5 font-medium rounded-full">
<div v-if="room.is_private === true" class="rounded-full py-1 px-2 bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100">
<span>Private</span>
</div>
<div v-else-if="room.is_private === false" class="rounded-full py-1 px-2 bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-100">
<span>Public</span>
</div>
<div v-else-if="room.is_private === 'true'" class="rounded-full py-1 px-2 bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100">
<span>Private</span>
</div>
<div v-else-if="room.is_private === 'false'" class="rounded-full py-1 px-2 bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-100">
<span>Public</span>
</div>
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-center">
<a class="text-md font-medium text-gray-900 dark:text-gray-50">99</a>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-md font-medium">
<div class="flex rounded-full py-2 px-4 bg-indigo-700 hover:bg-indigo-900">
<a href="#" #click="joinRoom(room)"
class="text-white">Enter</a>
</div>
</td>
</tr>
</tbody>
</table>
<div class="bg-gray-800 dark:bg-gray-900">
<div class="flex justify-end px-4 py-3 text-left text-s font-medium text-gray-50 uppercase tracking-wider">
<span class=" px-2 pt-2 text-xs leading-5 font-semibold rounded-full">
<a href="#">
<div class="flex rounded-full py-1 px-2 bg-green-700 text-green-100 hover:bg-green-800">
<PlusIcon class="h-5 w-5"/><span class="text-sm font-bold pl-0.5">Create Room</span>
</div>
</a>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</TransitionChild>
</div>
</Dialog>
</TransitionRoot>
</template>
<script>
import {Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot} from '#headlessui/vue'
import {ExclamationIcon, XIcon, PlusIcon} from '#heroicons/vue/outline'
import {types as RoomTypes} from "../../../Store/modules/rooms/rooms.types";
export default {
components: {
Dialog,
DialogOverlay,
DialogTitle,
TransitionChild,
TransitionRoot,
ExclamationIcon,
XIcon,
PlusIcon,
},
props: ['rooms', 'selectedRoomId'],
emits: ['onSelectRoom', 'onLeaveRoom', 'onClose'],
methods: {
joinRoom(room) {
this.$store.dispatch(RoomTypes.JOIN_ROOM, room);
this.selectedRoomId = this.room;
this.$emit('onClose');
}
},
props: {
isOpen: Boolean,
usersCount: Boolean
},
}
</script>
Main.vue
SNIPPET OF CODE
<section aria-labelledby="primary-heading"
class="dark:bg-gray-900 min-w-0 flex-1 h-full flex flex-col overflow-hidden lg:order-last">
<room-tabs :selectedRoomId="currentRoom.id" :rooms="joinedRooms"
#onSelectRoom="currentRoom = $event" #onLeaveRoom="leaveRoom($event)"/>
<message-container :messages="messages"
class="h-full pb-2 mb-2 pt-0 mt-0 shadow-md overflow-y-auto"/>
<input-box
:room="currentRoom"
v-on:messagesent="getMessages"
class="dark:bg-gray-800 px-6 pb-6 pt-4 dark:border-t-2 dark:border-gray-600 bottom-0 sticky"
/>
</section>
I know its inside methods: joinRoom that needs to change and I know its wrong where this.selectedRoomId is - I just dont know what I need to change/fix to make it turn the selected room into the active room when you click join.
Any help would be very much appreciated!
I would use mapState to effectively watch the value in the store that is being updated by this.$store.dispatch(RoomTypes.JOIN_ROOM, room);
So in a component that needs to know this value:
computed: {
...mapState(['STORE_NAME', 'STORE_VALUE']),
},
and then you should be able to use this.STORE_VALUE as a dynamically updated value

Getting my toggle to show correctly in laravel livewire

I have a pivot table that links my products and categories together. What I'm trying to do is in my edit page for a product I
have a list of all the categories and each category has a toggle button that will enable or disable that category for that product.
The problem I'm having is that all my categories is set to enabled, but I only have one enabled and the rest is supposed to be disabled
I'm using laravel 8 and livewire
Here is my code
namespace App\Http\Livewire\Products;
use App\Models\Product;
use Livewire\Component;
use App\Models\Category;
class Edit extends Component
{
public Product $product;
public bool $enabled;
public $name;
public $description;
public function mount()
{
$pcPivot = $this->product->categories()->where('product_id', $this->product->id)->exists();
if($pcPivot === true)
{
$this->enabled = true;
}else{
$this->enabled = false;
}
$this->name = $this->product->name;
$this->description = $this->product->description;
}
public function render()
{
$categories = Category::all();
return view('livewire.products.edit', [
'categories' => $categories,
]);
}
}
and here is my edit.blade.php
<div>
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">Edit Product</h3>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<form wire:submit.prevent="submit">
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="title" class="block text-sm font-medium leading-5 text-gray-700">
Name
</label>
<div class="rounded-md shadow-sm">
<input id="name" wire:model="product.name" class="flex-1 form-input block w-full min-w-0 transition duration-150 ease-in-out sm:text-sm sm:leading-5">
</div>
</div>
</div>
</div>
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="description" class="block text-sm font-medium leading-5 text-gray-700">
Description
</label>
<div class="rounded-md shadow-sm">
<textarea id="description" wire:model="product.description" rows="3" class="form-textarea mt-1 block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"></textarea>
</div>
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<span class="inline-flex rounded-md shadow-sm">
<button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition duration-150 ease-in-out">
Update
</button>
</span>
</div>
</form>
</div>
</div>
</div>
#include('spacer')
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">Categories</h3>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<x-th>Title</x-th>
<x-th>Enable/Disable</x-th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
#foreach($categories as $category)
<tr>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="flex items-center">
<div class="text-sm font-medium text-gray-900">
{{ $category->title }}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="mt-1 flex rounded-md">
<span role="checkbox" tabindex="0" aria-checked="false" class="#if($enabled) bg-indigo-600 #else bg-gray-200 #endif relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline">
<span aria-hidden="true" class="#if($enabled) translate-x-5 #else translate-x-0 #endif inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200">
<input id="enabled" type="checkbox" wire:model="enabled" class="invisible">
</span>
</span>
</div>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
If you check the documentation for Livewire, at lifecycle hooks... you will see that:
mount : Runs once, immediately after the component is instantiated, but before render() is called
So basically you are getting an "enabled" value once, before rendering the component,then you start rendering it, with that foreach, using the same "enabled" from mount for each item of your dataset.
Consider building your cursor with the enabled value inside for each record.

Resources