Search code examples
c#ajaxasp.net-coreasp.net-ajax

How to filter the product without reload the page in ASP.NET Core 6


I'm trying to filter product data by brand when the person is on the product category page. Here the view product category. So, I want to do the filter by brands by side bar on the left. I use ajax so that its cant be reload page every time user choose in brand button.

Here is the code :

@{
    ViewData["Title"] = "ProductCategory";
    Layout = "~/Views/Layout/_CategoryLayout.cshtml";
}
@{
    IEnumerable<Category> categories = ViewBag.Categories as IEnumerable<Category>;
    IEnumerable<Brand> brands = ViewBag.Brand as IEnumerable<Brand>;
    string currentUrl = Context.Request.GetDisplayUrl();
}
<input type="hidden" id="category-id" value="@Model.FirstOrDefault().CategoryId" />

<!-- SECTION -->
<div class="section">
    <!-- container -->
    <div class="container">
        <!-- row -->
        <div class="row">
            <!-- ASIDE -->
            <div id="aside" class="col-md-3">
                <!-- aside Widget -->
                <div class="aside">
                    <h3 class="aside-title">Brands</h3>
                    <div class="checkbox-filter">
                        @foreach (var item in brands)
                        {
                            <div class="input-checkbox">
                                <input type="checkbox" class="brand-checkbox" name="brand" id="@item.BrandId">
                                <label for="@item.BrandId">
                                    <span></span>
                                    @item.BrandName
                                    <small>(@item.Products.Count)</small>
                                </label>
                            </div>
                        }
                    </div>

                </div>
                <!-- /aside Widget -->
                <!-- aside Widget -->
                <div class="aside">
                    <h3 class="aside-title">Price</h3>
                    <div class="price-filter">
                        <div id="price-slider"></div>
                        <div class="input-number price-min">
                            <input id="price-min" type="number">
                            <span class="qty-up">+</span>
                            <span class="qty-down">-</span>
                        </div>
                        <span>-</span>
                        <div class="input-number price-max">
                            <input id="price-max" type="number">
                            <span class="qty-up">+</span>
                            <span class="qty-down">-</span>
                        </div>
                    </div>
                </div>
                <!-- /aside Widget -->
                
            </div>
            <!-- /ASIDE -->
            <!-- STORE -->
            <div id="store" class="col-md-9">
                <!-- store top filter -->
                <div class="store-filter clearfix">
                    <div class="store-sort">
                        @* <label>
                            Sort By:
                            <select class="input-select">
                                <option value="0">Popular</option>
                                <option value="1">Position</option>
                            </select>
                        </label>

                        <label>
                            Show:
                            <select class="input-select">
                                <option value="0">20</option>
                                <option value="1">50</option>
                            </select>
                        </label> *@
                    </div>
                    <ul class="store-grid">
                        <li class="active"><i class="fa fa-th"></i></li>
                        <li><a href="#"><i class="fa fa-th-list"></i></a></li>
                    </ul>
                </div>
                <!-- /store top filter -->
                <!-- store products -->
                <div class="row">
                    <!-- product -->
                    @foreach (var item in Model.Take(6))
                    {
                        <div class="col-md-4 col-xs-6">
                            <div class="product">
                                <a href="/post/@SlugGenerator.SlugGenerator.GenerateSlug(item.ProductName)[email protected]().ProductVariations.FirstOrDefault().ProductVarId" />
                                <div class="product-img">

                                    <img src="~/Contents/img/@item.ProductItems.FirstOrDefault().Image1" width="200" height="200" alt="">
                                        <div class="product-label">
                                            <span class="sale">-30%</span>
                                            <span class="new">NEW</span>
                                        </div>
                                    </div>
                                    <div class="product-body">
                                    @*  <p class="product-category">@item.Category.CategoryName.ToUpper()</p> *@
                                        <h3 class="product-name"><a href="#">@item.ProductName.ToUpper()</a></h3>
                                        <h4 class="product-price">[email protected]<del class="product-old-price">@* $@(item.Product.Price + 200) *@</del></h4>
                                        <div class="product-rating">
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                            <i class="fa fa-star"></i>
                                        </div>
                                        <div class="product-btns">
                                            <button class="add-to-wishlist"><i class="fa fa-heart-o"></i><span class="tooltipp">add to wishlist</span></button>
                                            <button class="add-to-compare"><i class="fa fa-exchange"></i><span class="tooltipp">add to compare</span></button>
                                            <button class="quick-view"><i class="fa fa-eye"></i><span class="tooltipp">quick view</span></button>
                                        </div>
                                    </div>
                    
                            </div>
                        </div>
                    }
                    <!-- /product -->
                </div>
                <!-- /store products -->
                <!-- store bottom filter -->
                <div class="store-filter clearfix">
                    <span class="store-qty">Showing 20-100 products</span>
                    <ul class="store-pagination">
                        <li class="active">1</li>
                        <li><a href="#">2</a></li>
                        <li><a href="#">3</a></li>
                        <li><a href="#">4</a></li>
                        <li><a href="#"><i class="fa fa-angle-right"></i></a></li>
                    </ul>
                </div>
                <!-- /store bottom filter -->
            </div>
            <!-- /STORE -->
        </div>
        <!-- /row -->
    </div>
    <!-- /container -->
</div>
<!-- /SECTION -->

The Ajax code filters the brand every time the user clicks choose:

@section Scripts {
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            const checkboxes = document.querySelectorAll('.brand-checkbox');

            checkboxes.forEach((checkbox) => {
                checkbox.addEventListener('change', function () {
                    // Ensure only one checkbox is checked at a time
                    checkboxes.forEach((otherCheckbox) => {
                        if (otherCheckbox !== this) {
                            otherCheckbox.checked = false;
                        }
                    });

                    // If a checkbox is checked, get its value, otherwise set to null
                    var selectedBrand = this.checked ? this.id : null;
                    var categoryId = $('#category-id').val();

                    $.ajax({
                        url: '@Url.Action("FilterByBrands", "ProductView")',
                        type: 'GET',
                        data: { brandid: selectedBrand, cateid: categoryId },
                        success: function (response) {
                            $('#product').html(response);
                        }
                    });
                });
            });
        });
    </script>
}

Here is the code for the controller:

[HttpGet]
public ActionResult FilterByBrands(int brandid, int cateid)
{
    ViewBag.Brand = _context.Brands.Include(n => n.Products).ToList();

    var product = _context.Products
                          .Where(n => n.BrandNavigation.BrandId == brandid 
                                      && n.CategoryId == cateid)
                          .Include(n => n.ProductItems)
                          .ThenInclude(n => n.ProductVariations)
                          .Include(n => n.Category)
                          .ToList();

    return PartialView("_FilterPartial",product);
}

The _FilterPartial view is the same like product category as the image above I mentioned, also the code.

I think the Ajax works correctly because every time I choose brand button and I open the network of website and choose Fetch/XHR. The server return for me like this Fetch/XHR and when I click it, its open a view like this view for me.

Does anyone know the problem? I want to not reload the page but it seem like return something else. I really appreciate any instructions.

Thank you


Solution

  • trying to filter product data by brand when the person is on the product category page.

    Make request from HTML client to backend that returns a partial view using Ajax or Fetch API, and then update target html content within success callback function, which is a common way to update view page dynamically without reloading.

    I think the Ajax works correctly because every time I choose brand button and I open the network of website and choose Fetch/XHR. The server return for me like this Fetch/XHR and when I click it, its open a view like this view for me.

    I suppose that your request returns expected partial view content of products filtered by brands, to update html content, we just need to set target html container with returned response.

    Based on your code, we can find you use id selector, $('#product').html(response); , to update view page, but we can not find the html element with id="product" in your view page.

    Based on your html structure, you can try to modify the code as below, to update parent html container of products.

    //...
    success: function (response) {
        $('#store .row').html(response);
        //...