DEV Community

Cover image for AJAX vs Livewire
Nasrul Hazim Bin Mohamad
Nasrul Hazim Bin Mohamad

Posted on

AJAX vs Livewire

When building interactive forms in Laravel applications, dependent dropdowns — where the options in one dropdown depend on the selection of another — are a common requirement.

For example, when a user selects a country, the city dropdown should update accordingly.

There are two popular ways to implement this:

  • The AJAX way (using JavaScript and API routes)
  • The Livewire way (pure PHP, reactive and modern)

Let’s explore both, compare them, and highlight when each approach shines.


🧪 Use Case: Country ➡ City Dropdown

Imagine a scenario in a travel booking system:

  • User selects a country
  • The system displays a list of cities based on that country

1. 💻 The AJAX Approach

Traditionally, developers used jQuery or plain JavaScript to send an AJAX request when the first dropdown changes. The backend returns city data in JSON, and JavaScript dynamically populates the second dropdown.

Sample Setup

<!-- Country Dropdown -->
<select id="country">
  <option value="MY">Malaysia</option>
  <option value="TH">Thailand</option>
</select>

<!-- City Dropdown -->
<select id="city"></select>

<script>
  $('#country').on('change', function() {
    let country = $(this).val();
    $.get('/api/cities/' + country, function(data) {
      $('#city').empty();
      $.each(data, function(index, city) {
        $('#city').append(`<option value="${city.id}">${city.name}</option>`);
      });
    });
  });
</script>
Enter fullscreen mode Exit fullscreen mode

2. ⚡ The Livewire Approach (No JavaScript, No API)

Laravel Livewire simplifies this entire flow — you can handle dependent dropdowns using only PHP and Blade, no need to write JS or expose any API routes.

How it Works

  • The country dropdown is bound using wire:model.live
  • When the value changes, Livewire updates the cities list in real-time
  • All logic lives inside a Livewire component

Sample Livewire Component (Simplified)

class LocationSelector extends Component
{
    public $country;
    public $city;
    public $cities = [];

    public $allCities = [
        'MY' => [
            ['id' => 'KUL', 'name' => 'Kuala Lumpur'],
            ['id' => 'PG', 'name' => 'Penang'],
        ],
        'TH' => [
            ['id' => 'BKK', 'name' => 'Bangkok'],
            ['id' => 'CNX', 'name' => 'Chiang Mai'],
        ],
    ];

    public function updatedCountry($value)
    {
        $this->city = null;
        $this->cities = $this->allCities[$value] ?? [];
    }

    public function render()
    {
        return view('livewire.location-selector');
    }
}
Enter fullscreen mode Exit fullscreen mode

Corresponding Blade View

<select wire:model.live="country">
  <option value="">Select Country</option>
  <option value="MY">Malaysia</option>
  <option value="TH">Thailand</option>
</select>

@if (!empty($cities))
  <select wire:model="city">
    <option value="">Select City</option>
    @foreach ($cities as $city)
      <option value="{{ $city['id'] }}">{{ $city['name'] }}</option>
    @endforeach
  </select>
@endif
Enter fullscreen mode Exit fullscreen mode

Absolutely! Here's a combined Pros and Cons section that directly compares AJAX and Livewire for handling dynamic dependent dropdowns:


⚖️ AJAX vs Livewire: Pros & Cons

Feature / Factor ✅ Livewire ✅ AJAX (jQuery / JS)
🧠 Ease of Implementation Straightforward — everything in PHP/Blade, no need to write JS Requires JavaScript, route/controller setup, and JSON handling
🔁 Reactivity / Real-time Updates Built-in reactivity using wire:model.live Requires manual event binding and DOM manipulation
🌐 API / Data Layer No API needed — uses internal component state Needs a dedicated API endpoint and possibly middleware
🧪 Testability Easy to write tests using Livewire component testing API needs to be tested separately from the JS layer
🔧 Flexibility / Control Works great for simple to moderate use cases More flexible for advanced, frontend-heavy interactivity
🧩 Reusability Tight coupling with Livewire views — not easily reusable outside Laravel API approach is reusable for Vue, mobile apps, or other consumers
⚙️ Debugging Debuggable within PHP stack, fewer moving parts More complex — inspect console/network tab, deal with async issues
🧱 Learning Curve Simple if already using Laravel + Livewire Familiar to most developers with basic JavaScript knowledge
🚀 Performance Can be slower with many components or heavy DOM updates Faster client-side rendering once data is fetched
🔒 Security Automatically handles CSRF, session state via Laravel Must handle CSRF, headers, and auth on the client manually

🎯 When to Use Which?

Situation Best Choice
You need fast interactivity Livewire
You’re building with full-stack JS AJAX (or Vue/Alpine)
You need to reuse the API elsewhere AJAX
You want less boilerplate & faster prototyping Livewire

🔚 Conclusion

If you’re already using Laravel Livewire, dependent dropdowns can be handled 100% in PHP with minimal effort.

It leads to cleaner code, faster prototyping, and fewer moving parts.

But if you’re exposing the same data to a frontend framework, mobile app, or need caching layers, the AJAX + API route might still be the more scalable approach.

Both are valid.

Choose the one that fits your project scale, team expertise, and desired maintainability.


📌 Which method do you prefer for dynamic dropdowns? Let me know in the comments!


Photo by Reuben Mergard on Unsplash

Top comments (0)