Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

Dependent Dropdowns: Country and Cities

Premium
4 min read

In this course section, we will build four small demo projects to practice Livewire more. The first project is a dependent dropdown, like a parent and a child.

When we will choose a country, the cities list will be refreshed.

dependent dropdowns


DB Structure

First, let's quickly see what the Migrations and Models look like.

database/migrations/xxx_create_countries_table.php:

Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});

app/Models/Country.php:

use Illuminate\Database\Eloquent\Relations\HasMany;
 
class Country extends Model
{
protected $fillable = [
'name',
];
 
public function cities(): HasMany
{
return $this->hasMany(City::class);
}
}

database/migrations/xxx_create_cities_table.php:

Schema::create('cities', function (Blueprint $table) {
$table->id();
$table->foreignId('country_id');
$table->string('name');
$table->timestamps();
});

app/Models/City.php:

class City extends Model
{
protected $fillable = [
'country_id',
'name',
];
}

And a simple seeder to have some data in the DB:

$country = Country::create(['name' => 'United Kingdom']);
$country->cities()->create(['name' => 'London']);
$country->cities()->create(['name' => 'Manchester']);
$country->cities()->create(['name' => 'Liverpool']);
 
$country = Country::create(['name' => 'United States']);
$country->cities()->create(['name' => 'Washington']);
$country->cities()->create(['name' => 'New York City']);
$country->cities()->create(['name' => 'Denver']);

Livewire Component

For the Livewire component, we will name it just Dropdowns.

php artisan make:livewire Dropdowns

In the component, we first must get the list of...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (29 h 14 min)

You also get:

54 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

J
Joe ✓ Link copied!

When using this type of technique, what would be the best way to provide useful feedback to the user in case of a communication disruption when they're using the select?

I know we can set the select (or even the whole form or page) to be disabled using wire:offline but consider a scenario where "United States" and "Washington" was already selected and then the user selected "United Kingdom" but at the exact moment they did that, the connection was disrupted, so the city stayed populated with the United States cities even though the country now shows United Kingdom. It might be a bit confusing for the user. So is there a way that we could somehow clear/reset the city dropdown when the country is clicked, before the response comes back, just in case the response never comes in order to improve UX?

DL
David Lun ✓ Link copied!

If your users have connectivity problems and this is very serious issue for you i'd suggest implementing this only client side.

But there's a catch, is it worth it if they can't submit the form anyway, due to... well... connectivity issues?

I'd stay with something simple, and move on, unless there's some good reason to do otherwise.

<div wire:offline>
    You are now offline. Press this button to reload the page.
</div>
J
Joe ✓ Link copied!

I was thinking more in terms of intermittent connectivity issues, such as using a mobile on a train for example. In such a case it's very likely that someone could choose a country and have it fail silently due to the connection dropping for 1 second but still be able to do everything else because the connection is back. And my concern would be that their overall perception of the app would be that it's buggy because they wouldn't understand why just that one thing failed, especially as there's no feedback to the user.

PK
Povilas Korop ✓ Link copied!

In my opinion, if someone tries to use any app on the unstable train connection, they KNOW that connection is unstable and totally wouldn't blame the app.

I would personally just validate the data on the back end.

DL
David Lun ✓ Link copied!

I understand, and my answer won't change at all. Let me explain my point of view:

  1. If you want to minimize chances packets being dropped you might want to reduce round trips as much as possible and have complete control what happens if the connection fails. Livewire is opposite of that.
  2. If there's no connection user cannot do anything, your application can only hope and retry request if connection comes back. Thus wire:offline with check your connection message seems sufficient for that.
  3. I'm not sure right now how Livewire handles retries because I didn't test this specific scenario, you should test that yourself. Or just have a simple blade form with a single POST request.
  4. Optionally you could do REST implementation and handle UI and Networking to cover this case and have complete control what you want to do.
  5. So now we have 3 ways (at least) to aproach it, Livewire wire:offline, http POST, and something in between with REST API. And yet there's no guarantee something won't fail due to connection, and the actual form is not the focus at this point, it can happen on any page load or action, and window can be 1 second to N.
  6. This would be my reasoning why I wouldn't focus on this problem a lot and just minimize impact by telling user that there's a problem on HIS side, and not a BUG with our application, especially it is ONLINE app, not offline app.
J
Joe ✓ Link copied!

Thank you for your detailed reply. Nothing you have said is technically wrong, but I'm thinking that maybe I haven't really explained myself properly.

Looking into this in more detail, the problem seems to be that if the user performs any Livewire request on a component at the split-second when the network is unavailable (because they are on a train, or for whatever other reason) the result is that the page breaks. And it doesn't break just while the network is offline, it is broken forever, until the page is refreshed.

There's no concept of a retry as far as I can tell. Livewire completely forgets that the request was attempted. If you look in the network tab of dev tools, it just shows as "(failed)". And you can't show a wire:offline message to tell the user to refresh the page, because that message would only display for the split second that the network connection was unavailable. As soon as the network is available again the message will disappear. But our page is still broken.

The point, though, is that the page breaks because of the user performing an action during that split second when the network is offline.

For a simple demonstration of what I mean, just go to the Filament Demo, click Customers and then click Edit for any customer until you find one with more than one address attached. Now, take your browser offline and press one of those "Detach" buttons. It will fail and show as a network error in dev tools. Now, bring your browser back online and try the "Detach" button again. It still doesn't work, but now there is no network error, or even an error in the console. It's completely silent and it will never work again unless you refresh the page.

The dropdown example of this lesson breaks in the same way. If the user happens to select the dropdown during a split second when the network is unavailable then the entire component is broken until the page is refreshed.

My apolgoies, perhaps this wasn't really the correct place to bring up this issue. I started by honestly thinking it was just an issue with the way this lesson instructed us to make the dropdown component, but I can see now that it's bascially an issue that affects Livewire globally and there's nothing specifically wrong with the tutorial on how to make this component.

DL
David Lun ✓ Link copied!

you're right

PK
Povilas Korop ✓ Link copied!

Yes that's how Livewire works. nothing we can do about it.

AS
ahmad sawaie ✓ Link copied!

I’m trying to get the value of select onchange with livewire and select2 jquery but when I start select2 I can’t get the value, without select2 the value gets normally.

N
Nerijus ✓ Link copied!

This course was made with livewire 2. If you are using livewire 3 there might be some differences how to make it

J
Joe ✓ Link copied!

Thank you guys! I'm really enjoying working through these courses and getting such detailed feedback on my thoughts and concerns like this is hugely valuable to my . I really appreciate it!

JP
Joao Pedro ✓ Link copied!

In case anyone select the "choose country" after already selected any city the app will break, to fix that you can put that in the updatedCountry method: "public function updatedCountry($value): void { $this->cities = City::where("country_id", $value)->get(); $this->city = $this->cities->first()?->id; } " and se the type of city as "?int"

J
Joe ✓ Link copied!

Turns out the original issue I described was actually caused by a bug in Livewire which was fixed in v3.4.7

https://github.com/livewire/livewire/pull/7972

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.