Laravel Livewire emit event in component with value not working - php

I have a blade. file with multiple livewire components:
<section class="">
<h2 id="page-goal">Add A New Item</h2>
#livewire('libraries.catalog-item-create', ['categories' => $categories, 'library' => $library])
#livewire('libraries.generic-publisher-create')
#livewire('libraries.generic-title-create')
#livewire('libraries.generic-artist-create')
#livewire('libraries.generic-tempo-create')
</section>
Each component is an input form that ends with a 'Next' button, ex:
<button
wire:click="nextStep()"
class="#if($next) bg-black text-white cursor-pointer #else bg-gray-500 text-gray-300 cursor-default #endif rounded w-20"
#if(! $next) disabled #endif >
Next
</button>
However, on the generic-artis-create form, I want to use the $emit format as follows:
<div class="flex flex-row">
<button
wire:click="$emit('nextStep','tempo')"
class="#if(count($artists) || ($artistObject && $artistTypeObject)) bg-black text-white cursor-pointer #else bg-gray-500 text-gray-300 cursor-default #endif rounded w-20"
#if(! $next) disabled #endif >
Next
</button>
</div>
I have a 'nextStep()' method in each Component which I use to advance the user through the components.
But, when I click the Next button with the direct $emit(), nothing happens, i.e. there's no Network activity. Livewire is brilliant, so I know I'm doing something wrong.
Any and all help is appreciated!

Sometimes asking the question leads to the answer. I was not completing the action which changed the state of the '$next' property, so the button was disabled. Fixing this allowed the $emit('name','value') to work.

Related

Chunking Results In Laravel Blade Failing Due To Callback

I am trying to chunk the results of a laravel collection in my blade template to have 3 columns of records expanding to as many rows as needed. What I have is...
#foreach(Auth::user()->apps()->chunk(3) as $chunk)
<div class="row row-grid gx-0">
#foreach($chunk as $app)
<a href="{{ $app->url }}" class="dropdown-item text-decoration-none p-3 bg-none">
<div class="position-relative">
<i class="fa-solid fa-circle-fill position-absolute text-theme top-0 mt-n2 me-n2 fs-6px d-block text-center w-100"></i>
<i class="fa-solid fa-{{ $app->icon }} h2 opacity-5 d-block my-1"></i>
</div>
<div class="fw-500 fs-10px text-white">{{ ucfirst($app->alias) }}</div>
</a>
#endforeach
</div>
#endforeach
But I am getting the error Too few arguments to function Illuminate\Database\Eloquent\Relations\BelongsToMany::chunk(), 1 passed in /app/storage/framework/views/7d3f05473ba9eb01ea58150355cc97e13e862587.php on line 1 and exactly 2 expected. Taking a look at the Laravel source in Github it appears as a callback function is required which handles the looping for each chunk but this only really works if done from within PHP itself, within a blade template I cant figure out how to to a chunk with a callback. All the information I have been able to find online for Laravel blade chunking shows that this should be working.
My controller method is...
$userApps = Auth::user()->apps();
$chunk = ceil($userApps->count() / 3);
return view('apps', ['apps' => $userApps, 'appsChunk' => $chunk]);

Laravel 8 - reusable code block, change variable depending on a page for charts?

I want to display multiple charts in a single page or different pages. How can I reuse the blade file instead of repeating/retyping the code?
I created a plain blade file _chart-widget.blade.php and I want the variable value to change depending on the page, or depending on what I want to set the variable in each <section> of a page
<!--begin::Charts Widget 1-->
<div class="card {{ $class ?? '' }}">
<!--begin::Header-->
<div class="card-header border-0 pt-5">
<!--begin::Title-->
<h3 class="card-title align-items-start flex-column">
<span class="card-label fw-bolder fs-3 mb-1">Recent Statistics</span>
<span class="text-muted fw-bold fs-7">More than 400 new members</span>
</h3>
<!--end::Title-->
<!--begin::Toolbar-->
<div class="card-toolbar">
<!--begin::Menu-->
<button type="button" class="btn btn-sm btn-icon btn-color-primary btn-active-light-primary" data-kt-menu-trigger="click" data-kt-menu-placement="bottom-end">
{!! theme()->getSvgIcon("icons/duotune/general/gen024.svg", "svg-icon-2") !!}
</button>
{{ theme()->getView('partials/menus/_menu-1') }}
<!--end::Menu-->
</div>
<!--end::Toolbar-->
</div>
<!--end::Header-->
<!--begin::Body-->
<div class="card-body">
<!--begin::Chart-->
<div id="kt_charts_widget_1_chart" style="height: 350px"></div>
<!--end::Chart-->
</div>
<!--end::Body-->
</div>
<!--end::Charts Widget 1-->
How can I make the code above dynamic and reusable when I #include it?
You can include views in Laravel blade template.
here you can read more.
Just use like this:
<div>
#include('_chart-widget')
</div>
If you need to pass data to your widget component, just give parameters as an array to your component:
#include('view.name', ['status' => 'complete'])
If you want variables to be different in each page simply pass vairables from Controller.If you are on the same page and including same blade multiple times this can help you:
#include('view.name', ['code' => 'complete'])
This will set different values for $code variable in different sections.
Check out documentation here.

Livewire search not making any results

I'm new to Livewire with some laravel experience and a good amount of php experience. My issue I'm trying to get a livewire search component to work. I'm using laravel 8 and livewire is installed. My nav menu is using livewire. SO I wish to insert a search into my layout as follows:
<body class="font-sans antialiased">
<x-jet-banner />
<div class="min-h-screen bg-gray-100">
#livewire('navigation-menu')
#livewire('search-accounts')
... rest of my layout ...
</div>
</body>
I have a Model Account which has the Accounts used by my app. Account uses Eloquent and is working fine.
I have created a livewire component app/Http/Livewire/SearchAccounts.php with the following content:
<?php
namespace App\Http\Livewire;
use App\Models\Account;
use Livewire\Component;
class SearchAccounts extends Component
{
public $search = '';
public function render()
{
return view('livewire.search-accounts', [
'accounts' => Account::where( 'name', $this->search )->get(),
]);
}
}
My blade template is resouces/views/livewire/search-accounts.blade.php and is as follows:
<div class="px-4 space-y-4 mt-8">
<form method="get">
<input class="border-solid border border-gray-300 p-2 w-full md:w-1/4"
type="text" placeholder="Search Accounts" wire:model="search"/>
</form>
<div wire:loading>Searching accounts...</div>
<div wire:loading.remove>
<!--
notice that $search is available as a public
variable, even though it's not part of the
data array
-->
#if ($search == "")
<div class="text-gray-500 text-sm">
Enter a term to search for accounts.
</div>
#else
#if($accounts->isEmpty())
<div class="text-gray-500 text-sm">
No matching result was found.
</div>
#else
#foreach($accounts as $account)
<div>
<h3 class="text-lg text-gray-900 text-bold">{{$account->name}}</h3>
<p class="text-gray-500 text-sm">{{$account->url}}</p>
<p class="text-gray-500">{{$account->ipaddress}}</p>
</div>
#endforeach
#endif
#endif
</div>
</div>
When I view my app in the browser the search bar is shown and contains a placeholder called Search Accounts. I click the search bar and start typing but no search is done (my browsers dev tools show no Network or console activity).
Have I missed something? I've tried php artisan livewire:discover and cleared caches. I have followed a tutorial (https://laravel-livewire.com/) and not sure why I'm not getting the expected results. Other posts like this are actually getting some network activity as the ajax requests are made which I'm not seeing at all.
thanks
Craig
Turned out that my #livewireScripts wasn't included in my master blade template. Once this was added livewire worked.
Try changing this
<input class="border-solid border border-gray-300 p-2 w-full md:w-1/4"
type="text" placeholder="Search Accounts" wire:model="search"/>
to
<input class="border-solid border border-gray-300 p-2 w-full md:w-1/4"
type="text" placeholder="Search Accounts" wire:model.debounce.500ms="search"/>
This should send a network request at most every 500ms after an event (helps to not hammer the backend with every keypress).
Have a look at this page of the docs https://laravel-livewire.com/docs/2.x/actions

Undefined Route

I am very new to laravel and I am really terrible with routing. I want to delete the specific data but it say that route is undefined
CandidateController.php
this is my method to delete
public function destroy(Form $candidates)
{
$candidates->delete();
return redirect()->route('candidate.approve');
}
route
Route::resource('candidates', CandidateController::class);
I am using a resourse, when I go through the tutorial, it shortened my code into above. When I clicked the button delete, it says that Undefined route [candidate.approve]. Can someone help me where I went wrong?
blade
#foreach ($candidates as $candidate)
<div class="modal__content">
<div class="p-5 text-center"> <i data-feather="x-circle" class="w-16 h-16 text-theme-6 mx-auto mt-3"></i>
<form action="{{ route('candidates.destroy', $candidate->id) }}" method="POST">
#csrf
#method('DELETE')
<div class="text-3xl mt-5">Are you sure?</div>
<div class="text-gray-600 mt-2">Do you really want to delete these records? This process cannot be undone.</div>
<button type="button" data-dismiss="modal" class="button w-24 border text-gray-700 dark:border-dark-5 dark:text-gray-300 mr-1">Cancel</button>
<button type="submit" title="delete" class="button w-24 bg-theme-6 text-white" >Delete</button>
</div>
<div class="px-5 pb-8 text-center">
</div>
</div>
</form>
</div>
#endforeach
web.php
Route::get('application/approve/{id}', 'CandidateController#postApprove')->name('application');
Route::get('candidate', [CandidateController::class, 'approve'])->name('candidate.approve');
Route::resource('candidates', CandidateController::class);
Just add new Route with candidate.approve name before Route::resource.
your web.php file will be like this
Route::get('your-url', [CandidateController::class, 'approve')->name('candidate.approve');
Route::resource('candidates', CandidateController::class);
But its better to use prural for named route, like the resource controller :
candidates.create
candidates.store
...
UPDATE
Since i know the flow of the app, you should use this on controller:
return back();
Why? because when admin click Delete on modal, it will goes to another URL to delete data from DB. After delete, return back() will redirect admin to previous URL

Cannot find the way to make #if statement works in blade

I'm making a "teacher's" app, and I want to make a log-in page which changes depending if there's registered users in the database or not.
I want to make a redirection button to a create user page if there aren't auth users in database, and to make a select user view if the database have one or more users.
The problem is that I don't know how to exactly do this, 'cause the view always shows me the first statement (what I've got in the if), also if in the database are registered users. Can anyone help me with this please?
This is the blade file:
#if (empty(Auth::user()->id))
<div class="grid-item" id="grid-item5">
<div id="title">
<h1>Welcome</h1>
<p>We see there aren't users</p>
</div>
<div id="loginForm">
<button type="button" onclick="window.location='{{ url("/newUser") }}'">Button</button>
</div>
</div>
#else
<div class="grid-item" id="grid-item5">
<div id="title">
<h1>Select an user</h1>
</div>
<div id="loginForm"></div>
</div>
#endif
Here you have the controller index method:
public function index()
{
$users = User::all();
return view('/', compact('users'));
}
And finally here you have the page:
The following code is the sample for it, kindly replace code accordingly
#if(!$user)
//show button
#else
//dont show button
#endif
I think your question is you want to check if there is user in database.
So no need to check if the user authenticated but to check if there is user on the database.
In your controller
public function index() {
return view('/', ['users' => User::all()]);
}
and in your blade file
#if(!$users)
<div class="grid-item" id="grid-item5">
<div id="title">
<h1>Welcome</h1>
<p>We see there aren't users</p>
</div>
<div id="loginForm">
<button type="button" onclick="window.location='{{ url("/newUser") }}'">Button</button>
</div>
</div>
#else
<div class="grid-item" id="grid-item5">
<div id="title">
<h1>Select an user</h1>
</div>
<div id="loginForm"></div>
</div>
#endif
This function will get the current authenticated user: Auth::user(). I guess what you are trying to achieve is #if(empty($users)) where $users is the variable you are passing on controller.
If you want to verify if the user that accessed to that view is authenticated you can simply use #auth and #guest.
Also i would suggest you to change your button to an <a> tag and your href would be <a href="{{ route('route.name') }}" where route.name would be defined in your routes file.
in your controller:
you can create a folder inside views called users and then the index.blade.php (views/users/index.blade.php)
public function index()
{
$users = Users::all();
return view('users.index')->with('users', $users);
}
in your view:
#if(count($users) < 1)
...
#else
...
#endif
count is validating if the $users array length is less then 1 (in other words if the array is empty).
Alternative you can you isEmpty()
#if($users->isEmpty())
...
#else
...
#endif

Categories