Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

remotemontes's avatar

Is it possible to have pretty URLs with Livewire 3 wire:model.live?

Hi All! I think this is my question here after a lot of years around.

I have this routes:

Route::get('/', ShowProducts::class)->name('products');
Route::get('/category/{categorySlug}', ShowProducts::class)->name('products');

I have this component:

namespace App\Livewire;
class ShowProducts extends Component
{
    use WithPagination;

    #[Url(as: 'category')]
    public $categorySlug = '';

    public function render()
    {
		return view('livewire.show-products', compact('products', 'webCategories'));
	}

And this on the view:

                <select wire:model.live="categorySlug">
                    <option value="">Any</option>
                    @foreach ($webCategories as $webCategory)
                        <option value="{{ $webCategory->slug }}">{{ ucfirst($webCategory->plural_name) }}</option>
                    @endforeach
                </select>

I can load this URL manually ant it works well: /category/fruit

But when I select and option on the select, Livewire updates current URL to this one: /?category=fruit

Is it possible to get Livewire using the first one?

0 likes
6 replies
LaryAI's avatar
Level 58

Yes, it is possible to have pretty URLs with Livewire 3 wire:model.live. To achieve this, you can use the wire:key directive in your Livewire component.

Here's how you can modify your code to have pretty URLs:

  1. In your Livewire component, add the wire:key directive to the <select> element. This will ensure that Livewire treats each <select> element as a separate component instance.
<select wire:model.live="keywordSlug" wire:key="keywordSlug">
    <option value="">Any</option>
    @foreach ($webKeywords as $webKeyword)
        <option value="{{ $webKeyword->slug }}">{{ ucfirst($webKeyword->plural_name) }}</option>
    @endforeach
</select>
  1. In your routes file, update the route definition for the /category/{keywordSlug} route to include a name parameter.
Route::get('/category/{keywordSlug}', ShowProducts::class)->name('products.category');
  1. In your Livewire component, update the render method to use the named route instead of the route class.
public function render()
{
    return view('livewire.show-products', [
        'products' => $products,
        'webKeywords' => $webKeywords,
    ])->extends('layouts.app');
}

With these changes, Livewire will update the URL to /category/fruit when you select an option in the <select> element.

remotemontes's avatar

@LaryAI Thanks Lary, but that doesn't seem to work, I still get the /?category=fruit type URL.

Additionally, you tell me to update the render method to use the named route instead of the route class, but I don't see that on your code.

Snapey's avatar

I'm confused, is $keywordSlug = "fruit" or "category/fruit"

remotemontes's avatar

@Snapey Yes you are right, is an old code I'm updating, now I updated the code without the confusing naming

remotemontes's avatar

@Snapey That's just the name for the query parameter, that just will change it from "/?category=fruit" to "/?categorySlug=fruit"

Please or to participate in this conversation.