How to prevent using a parameter when before clicked in Livewire - laravel

This code is a part of the View file connected with the Livewire component.
How to prevent using a parameter when before a button clicked?
View
...
#foreach ($babies as $baby)
...
<div
class="flex justify-between w-11-12 py-1 mb-1 ml-2 leading-6 text-sm font-medium ext-left text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-blue-800 focus:outline-none">
<button wire:click="setAte({{ $baby, $ate = 0 }})"
class="flex w-1-3 mr-1 px-2 text-xs font-medium text-center text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-pink-800 focus:ring-ring-600 {{ $baby['ate'] == 0 ? "bg-blue-500" : "bg-red-500" }}">
S</button>
<button wire:click="setAte({{ $baby, $ate = 1 }})"
class="flex w-1-3 mr-1 px-2 text-xs font-medium text-center text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-pink-800 focus:ring-pink-600 {{ $baby['ate'] == 1 ? "bg-blue-500" : "bg-red-500"}}">
M</button>
<button wire:click="setAte({{ $baby, $ate = 2}})"
class="flex w-1-3 px-2 text-xs font-medium text-center text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-pink-800 focus:ring-pink-600 {{ $baby['ate'] == 2 ? "bg-blue-500" : "bg-red-500" }}">
L</button>
<div>{{ $baby['ate'] }}</div> {{-- <---check code --}}
</div>
#endforeach
...
Component
public function setAte($baby, $ate)
{
$baby['ate'] = $ate;
$selectedBaby = Baby::find($baby['id']);
$selectedBaby->save();
}
Error
Illuminate\Contracts\Container\BindingResolutionException
Unable to resolve dependency [Parameter #1 [ $ate ]] in class App\Http\Livewire\Classroom\BabyStatus
Solution 1
//Component
public $baby;
protected $rules = [
'baby.ate' => 'required|int|min:0|max:2'
];
public function updateAte($ate)
{
$this->baby->ate = $ate;
$this->baby->save();
}
//View
<button wire:model="baby" wire:click="updateAte(0)"
class="flex w-1-3 mr-1 px-2 text-xs font-medium text-center text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-pink-800 focus:ring-ring-600 {{ $baby['ate'] == 0 ? "bg-blue-500" : "bg-red-500"}}">S</button>
<button wire:model="baby" wire:click="updateAte(1)"
class="flex w-1-3 mr-1 px-2 text-xs font-medium text-center text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-pink-800 focus:ring-pink-600 {{ $baby['ate'] == 1 ? "bg-blue-500" : "bg-red-500"}}">M</button>
<button wire:model="baby" wire:click="updateAte(2)"
class="flex w-1-3 px-2 text-xs font-medium text-center text-white uppercase transition rounded shadow ripple hover:shadow-lg hover:bg-pink-800 focus:ring-pink-600 {{ $baby['ate'] == 2 ? "bg-blue-500" : "bg-red-500" }}">L</button>
That's all, thank you #Unflux.

I would be inclined to refactor what you have and make each baby a separate livewire component.
App\Http\Livewire\Baby.php
class Baby extends Component
{
// your instance of a baby
public $baby;
// required to allow updating of the baby properties
protected $rules = [
'baby.ate' => 'required|int|min:0|max:2'
];
public function render()
{
return view('livewire.baby');
}
// you can set the value of properties here if you want
public function mount()
{
// for example:
//$this->baby->ate = -100;
}
// when the value of ate is updated from the view
// update the baby model
public function updatedBaby()
{
$this->baby->save();
}
}
resoures\views\livewire\baby.blade.php
<div class="p-4 m-4">
<h4>Baby Component - ate: {{ $baby->ate }}</h4>
<div class="flex justify-between p-4 m-4">
<button wire:click="$set('baby.ate', 0)"
class="text-white px-2 rounded {{ $baby->ate === 0 ? "bg-blue-500" : "bg-red-500" }}">S
</button>
<button wire:click="$set('baby.ate', 1)"
class="text-white px-2 rounded {{ $baby->ate === 1 ? "bg-blue-500" : "bg-red-500" }}">M
</button>
<button wire:click="$set('baby.ate', 2)"
class="text-white px-2 rounded {{ $baby->ate === 2 ? "bg-blue-500" : "bg-red-500" }}">L
</button>
</div>
</div>
Note: The use of === in the above. Prevents null or similar values being incorrectly determined as equal to 0.
Then in your view:
#foreach($babies as $baby)
#livewire("baby", ["baby" => $baby]) // render your single baby component
#endforeach

Related

Laravel cannot find a Controller Method

Method App\Http\Controllers\CommunityController::show does not exist
My route
Route::get('/community/{id}', [CommunityController::class, 'community'])
->name('profile.community');
Controller
public function community($id)
{
$communityProfile = Community::find($id);
/* $join = CommunityUser::join('communities', 'communities.user_id', '=', 'community_users.user_id')->get(); */
return view('user.comprofile', compact('communityProfile', 'join'));
}
View community
#for ($i = 0; $i < 3; $i++)
<a href=" {{ route('profile.community', $communities[$i]->id) }} ">
<div class="w-full p-6 overflow-hidden bg-white border hover:bg-gray-50 border-gray-200 rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<h5 class="mb-2 text-2xl font-semibold tracking-tight text-gray-900 dark:text-white">{{$communities[$i]->community}}</h5>
<p class="mb-3 font-normal text-gray-500 dark:text-gray-400 flex gap-3">
<x-iconsax-out-location class="text-[#F15E4A] w-5"/> {{$communities[$i]->address}}, {{$communities[$i]->city}}
</p>
<div class="flex gap-2">
<a href="#" class="inline-flex items-center font-semibold text-[#F15E4A] hover:underline cursor-default">
{{ $communities[$i]->type }}
</a>
#if ($communities[$i]->user_id === Auth::user()->id)
<span class="text-sm text-gray-500 pt-1">{{__('Created by: ')}}</span>
{{Auth::user()->name}}
#else
<span class="text-sm text-gray-500 pt-1">{{__('Created by: ')}}</span>
{{ $communities[$i]->name }}
#endif
</div>
</div>
</a>
#endfor
I am trying to view the community created by users but it gives me "cannot find a Controller Method ".
This can have several causes. Therefore, here is a small checklist:
The controller path is missing from your route:
use App\Http\Controllers\CommunityController; // this line
Route::get('/community/{id}', [CommunityController::class, 'community'])->name('profile.community');
Your CommunityController class name is misspelled
The namespace of the CommunityController is wrong
And then just to be sure, run: php artisan route:clear.

Livewire component vanish after emitting event

I made chat app using livewire, and i want to emit an event where in that event emitting antohter event to another component, but when i emit the event the component it self vanish from view, and i dont know why here is my code
<div class="flex flex-row py-2 px-2 items-center border-b-2 cursor-pointer hover:bg-gray-100" wire:click="$emit('chatUserSelected',{{$conversation}})">
and the event in chatlist component
protected $listeners = ['chatUserSelected'];
public $conversations;
public $selectedConversation;
public function chatUserSelected(Conversation $conversation)
{
$this->selectedConversation = $conversation;
$receiverInstance = KontakModel::find($conversation->kontak_id);
$this->emitTo('chat.chat-box','loadConversation',$this->selectedConversation,$receiverInstance);
$this->emitTo('chat.send-message','updateSendMessage',$this->selectedConversation,$receiverInstance);
}
public function mount()
{
$this->auth_id = auth()->id();
$this->conversations = Conversation::orderBy('last_time_message','DESC')->where('solved_at',NULL)->get();
// dd($this->conversations);
}
public function render()
{
return view('livewire.chat.chat-list', );
}
here is my view before emitting event
and after emitting event
the chatlist somehow disappear
for additional this is code for my main view
<div class="flex flex-row justify-between bg-white h-screen" x-data="chatApp">
#livewire('chat.chat-list')
#livewire('admin.side-bar')
<!-- message -->
#livewire('chat.chat-box')
<!-- end message -->
</div>
chat.chat-list.blade.php
<div class="overflow-y-auto">
#forelse ($conversations as $conversation)
<div class="flex flex-row py-2 px-2 items-center border-b-2 cursor-pointer hover:bg-gray-100" wire:key="{{$conversation->id}}" wire:click="$emit('chatUserSelected',{{$conversation}})">
<div class="w-1/4">
<img
src="https://source.unsplash.com/otT2199XwI8/600x600"
class="object-cover h-12 w-12 rounded-full"
alt=""
/>
</div>
<div class="w-full">
<div class="text-lg font-semibold">{{ $conversation->kontak->name }}</div>
<span class="text-gray-500">{{$conversation->messages->sortBy('created_at')->last()->body}}</span>
</div>
<div class="w-2/12">
#php
$unread = $conversation->messages->where('status', NULL)->where('category','receive')->count()
#endphp
#if ($unread > 0)
<div class="text-sm text-center font-light rounded-full bg-red-600 text-white min-w-5 h-5">{{$unread}}</div>
#endif
<span class="text-xs">{{$conversation->messages->sortBy('created_at')->last()->created_at->shortAbsoluteDiffForHumans()}}</span>
</div>
</div>
#empty
<div class="flex flex-row py-2 px-2 items-center border-b-2 text-2xl text-center">
<div class="text-center m-auto">
No Conversation
</div>
</div>
#endforelse
</div>

How to pass Model as parameters to the Wire (Livewire Laravel)

In the button, I can't pass Model product as parameters to the Wire (Livewire Laravel).
I have two function initiateEdit first in model stockin and the other in model product.
in this code only call the function that found in the stockin model but i want the function in the product model.
how to call the function for the specific model ?
<button
class="flex items-center p-2 text-sm font-medium leading-5 text-center text-white transition-colors duration-150 bg-gray-600 border border-transparent rounded-lg active:bg-gray-600 hover:bg-gray-700 focus:outline-none focus:shadow-outline-gray"
wire:click="$emit('initiateEdit', {{ $product['id'] }} )"
title="{{ __('Edit') }}">
<x-heroicon-o-pencil class="w-5 h-5" />
{{ $slot ?? '' }}
</button>
public function initiateEdit($id)
{
dd($id);
$this->selectedModel = $this->model::find($id);
}

Laravel set class if radio button selected

I have these radio buttons:
It's a separate Laravel blade component.
#props(['active'])
#php
$classes = ($active ?? false)
? 'group relative border bg-white py-3 px-4 flex items-center justify-center text-black text-sm font-semibold uppercase focus:outline-none sm:flex-1 shadow-sm cursor-pointer transition duration-150 ease-in-out'
: 'group relative border py-3 px-4 flex items-center justify-center text-gray-300 text-sm font-semibold uppercase focus:outline-none sm:flex-1 shadow-sm cursor-pointer duration-150 ease-in-out';
#endphp
<label {{ $attributes->merge(['class' => $classes]) }}>
<input type="radio" name="size" value="{{ $slot }}" class="sr-only">
<span> {{ $slot }} </span>
<span class="absolute -inset-px pointer-events-none" aria-hidden="true"></span>
</label>
I call it on a different page like so:
<x-product-size>XS</x-product-size>
How do I change the variable if it's selected? I can only find solutions on changing it depending on the route by doing something like this:
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-nav-link>
You can use JS for this purpose.
add an id to your radio input for example radioID.
<input type="radio" id="radioID" name="size" value="{{ $slot }}" class="sr-only">
and:
<script>
$(document).ready(function () {
$('#radioID').on('change', function () {
var selected = this.value;
if(selected == "XS") // or a variable
var slot = "some data";
{
$("#spanID").append(' + slot + ');
}
});
});
</script>
If you want to add active to a div, span or something other you can do it like this using their CLASS or ID:
$('.someclass').first().addClass('active');
$('#someid').first().addClass('active');

Bind Livewire component to parent array

I have the following structure:
A parent component:
class SiteEditComponent extends Component
{
protected $listeners = ['upClicked', 'downClicked', 'childUpdated'];
public $childBlocks = [];
public function render()
{
return view('livewire.site-edit-component', ['childBlocks' => $this->childBlocks]);
}
}
Which renders that way:
<div>
<button wire:click="addBlock" type="button" class=" mb-3 inline-flex items-center px-2.5 py-1.5 border border-gray-300 shadow-sm text-xs font-medium rounded text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Block hinzufügen</button>
#foreach($childBlocks as $key => $childBlockContent)
<livewire:templates.text-block-component wire:model.debounce="childBlocks.key" :block="$childBlockContent" :wire:key="$key">
#endforeach
</div>
And the child component(s):
class TextBlockComponent extends Component
{
public $block;
protected $rules = [
'block.title' => ''
];
public function render()
{
return view('livewire.text-block-component', [
'block' => $this->block
]);
}
Which renders that way (simplified):
<div>
<div class="bg-white shadow sm:rounded-lg mb-3">
<div class="px-4 py-5 sm:p-6">
<div
class=" w-1/3 border border-gray-300 rounded-md px-3 py-2 shadow-sm focus-within:ring-1 focus-within:ring-indigo-600 focus-within:border-indigo-600">
<label for="name" class="block text-xs font-medium text-gray-900">Titel</label>
<input wire:model.debounce="block.title" type="text" name="title" id="name"
class="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 focus:ring-0 sm:text-sm"
placeholder="Blocküberschrift">
</div>
</div>
</div>
</div>
In fact both components represent a Laravel model. A site can have multiple blocks.
What would be the right way to keep track of the child components in the parent component?
I want to implement a save button which should collect all items of $childBlocks, save the Site and attach the childBlocks to it. I tried to model it by using wire:model.debounce="childBlocks.key" but the binding doesn't seem to work.
I wanted to create an associative array in which every block is identified by a randomly generated key which holds the block data.

Resources