skip to Main Content

I am creating a recipe blog website. While creating post, I have option to categorize them into Veg and NonVeg posts using an Enum dropdown. The posts are displayed as cards on index page. I want to create a dropdown filter on index page to display only the selected category.

Enum:

public enum PostCategory
{
    [Display(Name = "Veg")]
    Veg = 0,

    [Display(Name = "NonVeg")]
    NonVeg = 1
}

Model:

public class Post
{
    // Post
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string? Link { get; set; }
    public string? Ingredient { get; set; }
    public string Recipe { get; set; }
    public string Image { get; set; }
    
    // Category
    public PostCategory PostCategory { get; set; }
}

Controller:

// Index
[HttpGet]
public async Task<IActionResult> Index()
{
    IEnumerable<Post> posts = await _postInterface.GetAll();
    return View(posts);
}

// Search Bar
[HttpPost]
public async Task<IActionResult> Index(string searchString, PostCategory postCategory)
{
    var posts = from p in _context.Posts select p;

    if (!string.IsNullOrEmpty(searchString))
    {
        posts = posts.Where(t => t.Title!.Contains(searchString));
    }

    return View(await posts.ToListAsync());
}

// Category Filter goes here.

View:

<!-- Filter -->
<div class="row justify-content-between">
    <!-- Search bar -->
    <div class="col-4">
        <form class="d-flex mb-2" role="search" asp-controller="Post" asp-action="Index">
            <input class="form-control me-2" type="search" placeholder="Search Posts" aria-label="Search" name="SearchString" required oninvalid="this.setCustomValidity(' ')" />
            <button class="btn btn-outline-success me-2" type="submit">Search</button>
            <a class="btn btn-outline-danger" asp-area="" asp-controller="Post" asp-action="Index">Reset</a>
        </form>
    </div>
    <!-- Dropdown -->
    <div class="col-4">
        <form  asp-controller="Post" asp-action="Index" id="category">
            <select class="form-control" asp-items="@Html.GetEnumSelectList<PostCategory>()" id="post-filter">
                <option value="">All</option>
            </select>
            <button class="btn btn-outline-success me-2" type="submit">Search</button>
            <a class="btn btn-outline-danger" asp-area="" asp-controller="Post" asp-action="Index">Reset</a>
        </form>
    </div>
</div>


<!-- Cards -->
<div class="album py-5 bg-light">
    <div class="container">

        <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3" id="post-recipe">

            @foreach (var item in Model)
            {
                <div class="col mb-4">
                    <div class="card shadow-sm">
                        <img class="bd-placeholder-img card-img-top" src="@item.Image" width="157" height="236" alt="Card image cap">
                        @* Card Details *@
                        <div class="card-body">
                            <a asp-controller="Post" asp-action="Detail" asp-route-id="@item.Id" class="stretched-link"></a>
                            <h6 class="card-text"> @item.Title </h6>
                            <div class="d-flex justify-content-between align-items-center">
                                <small class="text-body-secondary">@item.PostCategory</small>
                            </div>
                        </div>
                        @* Admin privlages *@
                        <div class="card-footer btn-group">
                            <a asp-controller="Post" asp-action="Edit" asp-route-id="@item.Id" type="button" class="btn btn-sm btn-outline-primary stretched-link">Edit</a>
                            <a asp-controller="Post" asp-action="Delete" asp-route-id="@item.Id" type="button" class="btn btn-sm btn-outline-danger stretched-link">Delete</a>
                        </div>
                    </div>
                </div>
            }

        </div>

    </div>
</div>

I have tried using adding additional [HttpPost] action in Index for it to only crash route with searchbar action. Combining it with searchbar action helps, as there is no Route crash, but even then, the code is only half complete, not giving the expected results, only showing veg category.

Here is what I have tried:

// Enum Category
[HttpPost]
public IActionResult Index(PostCategory postCategory)
{
    var posts = _context.Posts.Where(c => c.PostCategory == postCategory).ToList();
    return View(posts);
}

Thank you!

2

Answers


  1. Chosen as BEST ANSWER

    This is the final code I have got that works.

    
    // Filter
    [HttpPost]
    public async Task<IActionResult> Index(string searchString, PostCategory? postCategory)
    {
        var post = from p in _context.Posts select p;
    
        // Searchbar
        if (!string.IsNullOrEmpty(searchString))
        {
            post = post.Where(t => t.Title!.Contains(searchString));
        }
    
        // Category Dropdown
        if (postCategory != null)
        {
            post = _context.Posts.Where(c => c.PostCategory == postCategory);
        }
    
        return View(await post.ToListAsync());
    }
    
    

  2. the code is only half complete, not giving the expected results, only
    showing veg category

    You failed model-binding and PostCategory enum has the default value 0(Veg)

    Add the name property to your dropdownlist for model-binding,

    <select class="form-control" asp-items="@Html.GetEnumSelectList<PostCategory>()" name="postCategory" id="post-filter">
        <option value="">All</option>
    </select>
    

    also,modify your controller,add the codes for when you select all :

    [HttpPost]
    public IActionResult Index(PostCategory? postCategory)
    {
        List<Post> posts;
        if(postCategory!=null)
        {
             posts = _context.Post.Where(c => c.PostCategory == postCategory).ToList();
            
        }
        else
        {
            //wheather you don't select or select all,postCategory would be null
            //you could replace the logic here yourself
            posts = _context.Post.ToList();
           
        }
        return View(posts);
    }
    

    Result:
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search