Laravel 9 product filters using custom price range slider and ajax

Laravel 9 product filters using custom price range slider and ajax

Product filters for a website is very much essential for its's user's now a days. It gives your visitors flexibility to choose their desire product between a price range. We can filter products lots of way like their category, subcategory, tags, gorups, colors, size, price range and many more. In this lesson we will learn filter products among a price range using laravel, ajax and price range slider, also filter products by highest and lowest price. We don't use any third party slider plugin but we make a nice slider using few lines custom javascript code. For doing this task we have to following the bellow steps.

 

 

1. New or existing project

2. Create database and connect

3. Make model and migration

4. Add products field in migration file and run migrate command

5. Insert some products in table

6. Create routes

7. Create controller and write logics

8. Create css and js for custom slider

9. Create blade file inside views

10. Test app

 

 

 

 

Step-1: New or existing project

 

At the beginning of the tutorial we will install a new laravel project. If you wish you can apply this in your existing project.

Create a new project name product-filters in your machine using the composer command

composer create-project laravel/laravel product-filters

 

 



Step-2: Create database and connect

 

You can use your old database or just create a new one and placed database info in project .env file show in bellow. 

 

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=product_filters
DB_USERNAME=root
DB_PASSWORD=

 

 

 

Step-3: Make model and migration

 

Using the bellow artisan command let's our model and migration file

//model and migration 
php artisan make:model ProductFilter -m

 

 

 

 

Step-4: Add products field in migration file and run migrate command

 

See inside database directory migration file has created and in App\Models ProductFilter.php model is create. Ok, now we add all requred fileds for create_product_filters_table.php into migration file shown as bellow.

 

create_product_filters_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('product_filters', function (Blueprint $table) {
            $table->id();
            $table->string('image')->nullable();
            $table->string('name');
            $table->text('description')->nullable();
            $table->double('price');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('product_filters');
    }
};

 

 

 

 

Step-5: Insert some products in table

 

Insert some products so that you can display in frontend and search by a price range. We are not focusing on product insert but we focus on searching. You can store your products into database manually, using seeder, factory or upload by a csv file etc.

Note: for insert product image don't forget to make an images folder inside public directory.

 

 

 

Step-6: Create routes

 

Just create two routes in web.php file, first one is for displaying all products and second one is for search query

Note : Don't forget to import your controller at top of the file

 

web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductFilterController;


Route::get('/',[ProductFilterController::class,'all_products'])->name('all.products');
Route::get('/search-product',[ProductFilterController::class,'search_products'])->name('search.products');
Route::get('/sort-by',[ProductFilterController::class,'sort_by'])->name('sort.by');

 

 

 

 

Step-7: Create controller and write logics

 

Run artisan command for create controller and paste the code in your own controller

php artisan make:controller ProductFilterController

ProductFilterController.php
<?php

namespace App\Http\Controllers;

use App\Models\ProductFilter;
use Illuminate\Http\Request;

class ProductFilterController extends Controller
{
    public function all_products()
    {
        $all_products = ProductFilter::all();
        return view('welcome',compact('all_products'));
    }

    public function search_products(Request $request)
    {
        $all_products = ProductFilter::whereBetween('price',[$request->left_value, $request->right_value])->get();
        return view('search_result',compact('all_products'))->render();
    }

    public function sort_by(Request $request)
    {
        if($request->sort_by == 'lowest_price'){
            $all_products = ProductFilter::orderBy('price','asc')->get();
        }
        if($request->sort_by == 'highest_price'){
            $all_products = ProductFilter::orderBy('price','desc')->get();
        }
        return view('search_result',compact('all_products'))->render();

    }

}

 

 

 

 

Step-8: Create css and js for custom slider

 

We build a custom js slider, so for that we need some css and js code for design and get slider range value. If you want to user other slider than it's up to you means you are free to use other slider, just skip this step. But if you are ready to use our custom slider just create a css and js file and paste the bellow code. Now create a css file named style.css and a js file name script.js inside the public\css and public\js directory.

 

public\css\style.css


#rangeValue {
    position: relative;
    text-align: center;
    width: 60px;
    font-size: 1.25em;
    color: #fff;
    background: #27a0ff;
    margin-left: 15px;
    border-radius: 25px;
    font-weight: 500;
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1), -5px -5px 10px #fff, inset 5px 5px 10px rgba(0, 0, 0, 0.1), inset -5px -5px 5px rgba(255, 255, 255, 0.05);
}

.middle {
    position: relative;
    width: 100%;
    max-width: 500px;
    margin-top: 10px;
    display: inline-block;
}

.slider {
    position: relative;
    z-index: 1;
    height: 10px;
    margin: 0 15px;
}

.slider>.track {
    position: absolute;
    z-index: 1;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    border-radius: 5px;
    background-color: #b5d7f1;
}

.slider>.range {
    position: absolute;
    z-index: 2;
    left: 25%;
    right: 25%;
    top: 0;
    bottom: 0;
    border-radius: 5px;
    background-color: #27a0ff;
}

.slider>.thumb {
    position: absolute;
    z-index: 3;
    width: 30px;
    height: 30px;
    background-color: #27a0ff;
    border-radius: 50%;
}

.slider>.thumb.left {
    left: 25%;
    transform: translate(-15px, -10px);
}

.slider>.thumb.right {
    right: 25%;
    transform: translate(15px, -10px);
}

.range_slider {
    position: absolute;
    pointer-events: none;
    -webkit-appearance: none;
    z-index: 2;
    height: 10px;
    width: 100%;
    opacity: 0;
}

.range_slider::-webkit-slider-thumb {
    pointer-events: all;
    width: 30px;
    height: 30px;
    border-radius: 0;
    border: 0 none;
    background-color: red;
    cursor: pointer;
    -webkit-appearance: none;
}

#multi_range {
    margin: 0 auto;
    background-color: #27a0ff;
    border-radius: 20px;
    margin-top: 20px;
    text-align: center;
    width: 90px;
    font-weight: 500;
    font-size: 1.25em;
    color: #fff;
}

 

 

public\js\script.js


const input_left = document.getElementById("input_left");
const input_right = document.getElementById("input_right");

const thumb_left = document.querySelector(".slider > .thumb.left");
const thumb_right = document.querySelector(".slider > .thumb.right");
const range = document.querySelector(".slider > .range");

const set_left_value = () => {
    const _this = input_left;
    const [min, max] = [parseInt(_this.min), parseInt(_this.max)];

    _this.value = Math.min(parseInt(_this.value), parseInt(input_right.value) - 1);

    const percent = ((_this.value - min) / (max - min)) * 100;
    thumb_left.style.left = percent + "%";
    range.style.left = percent + "%";
};

const set_right_value = () => {
    const _this = input_right;
    const [min, max] = [parseInt(_this.min), parseInt(_this.max)];

    _this.value = Math.max(parseInt(_this.value), parseInt(input_left.value) + 1);

    const percent = ((_this.value - min) / (max - min)) * 100;
    thumb_right.style.right = 100 - percent + "%";
    range.style.right = 100 - percent + "%";
};

input_left.addEventListener("input", set_left_value);
input_right.addEventListener("input", set_right_value);

function left_slider(value) {
    document.getElementById('left_value').innerHTML = value;
}
function right_slider(value) {
    document.getElementById('right_value').innerHTML = value;
}

 

 

 

 

Step-9: Create blade file inside views

 

Now we will create our all required blade files inside resources\views

 

welcome.blade.php

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="csrf-token" content="{{ csrf_token() }}">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
      <link rel="stylesheet" href="{{ asset('css/style.css') }}">
    <title>Laravel 9 Ajax Product Filters</title>
  </head>
  <body>
      <div class="container">
         <div class="slider-area">
             @include('slider')
         </div>
          <div class="search-result">
              @include('search_result')
          </div>
      </div>

     <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
     <script src="{{ asset('js/script.js') }}"></script>
     <script>
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });
     </script>
     <script>
        $(document).ready(function(e){
           $('.range_slider').on('change',function(){
               let left_value = $('#input_left').val();
               let right_value = $('#input_right').val();
               // alert(left_value+right_value);
               $.ajax({
                   url:"{{ route('search.products') }}",
                   method:"GET",
                   data:{left_value:left_value, right_value:right_value},
                   success:function(res){
                      $('.search-result').html(res);
                   }
               });
           });

           $('#sort_by').on('change',function(){
               let sort_by = $('#sort_by').val();
               $.ajax({
                   url:"{{ route('sort.by') }}",
                   method:"GET",
                   data:{sort_by:sort_by},
                   success:function(res){
                       $('.search-result').html(res);
                   }
               });
           });
        })
     </script>

</body>
</html>

 

 

slider.blade.php


<div class="row">
    <div class="col-md-12 bg-info">
        <h2 class="text-center">Laravel-9 Ajax Product Filter With Price Range Slider</h2>
    </div>
    <div class="col-md-5 mb-3">
        <div class="middle">
            <div id="multi_range">
                <span id="left_value">25</span><span> ~ </span><span id="right_value">75</span>
            </div>
            <div class="multi-range-slider my-2">
                <input type="range" id="input_left" class="range_slider" min="0" max="100" value="25" onmousemove="left_slider(this.value)">
                <input type="range" id="input_right" class="range_slider" min="0" max="100" value="75" onmousemove="right_slider(this.value)">
                <div class="slider">
                    <div class="track"></div>
                    <div class="range"></div>
                    <div class="thumb left"></div>
                    <div class="thumb right"></div>
                </div>
            </div>
        </div>
    </div>
    <div class="col-md-5 mt-4 pt-2">
        <div class="middle">
            <div class="multi-range-slider my-2">
                <select name="sort_by" id="sort_by" class="form-control">
                    <option value="">Sort By</option>
                    <option value="highest_price">Highest Price</option>
                    <option value="lowest_price">Lowest Price</option>
                </select>
            </div>
        </div>
    </div>
</div>

 

 

search_result.blade.php


@if($all_products->count() >=1)
    <div class="row">
        @foreach($all_products as $product)
            <div class="col-md-3 my-2">
                <div class="card" >
                    <img src="{{ asset('images/'.$product->image) }}" class="card-img-top" style="height:250px;">
                    <div class="card-body">
                        <h5 class="card-title">{{ $product->name }}</h5>
                        <p class="card-text">{{ $product->description }}</p>
                        <h4 class="btn btn-dark">Price ${{ $product->price }}</h4>
                    </div>
                </div>
            </div>
        @endforeach
@else
        <div class="col-md-12 my-5 text-center">
            <h2>Nothing Found</h2>
        </div>
    <div>
@endif

 

 

 

 

Step-10: Test app

 

Everything has done, run artisan command and test your app.

php artisan serve

 

 

 

Hope this will helps a lot. Thanks

 

 

 

 

If you like what you are reading, please think about buying us a coffee as a token of appreciation.

Buy Me A Coffee

We appreciate your support and are committed to providing you useful and informative content.

We are thankful for your ongoing support 

 

 

 

 

You May Read Bellow Articles:

 

 

Laravel 9 live search data in a table using ajax

 

How to send SMS in laravel 9 using Twilio SMS API-Webjourney

 

Laravel 9 pdf invoice generate and download with barryvdh dompdf

 

How to create multi language website by laravel 9

 

Laravel 10 multiple form validation on the same page-WebJourney

 

Multiple parameter pass through Route & URL in Laravel-WebJourney

Tags

  • Share This: