4

I'm trying to provide user input from the view, call an action method from the controller, using the input to filter the model, then return the same view with the filtered model.

App View:

<div class="form-group">
    <div class="row">
        <div class="col-xs-3">
            Enter your budget, and we'll show you all the movies you can afford:
        </div>
        <div class="col-xs-3">
            <input type="text" class="form-control" id="budget" />
        </div>
        <div class="col-xs-3">
            <input type="submit" class="btn" id="budgetSubmit" onclick="budgetFilter()" />
        </div>
    </div>
    <div class="row">
        <div class="col-xs-3 col-xs-offset-3">
            <label id="budgetValidation"></label>
        </div>
    </div>
    <br />
    <table class="table" id="budgetTable">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Title)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.ReleaseDate)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Genre)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Price)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.Title)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.ReleaseDate)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Genre)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Price)
                    </td>
                </tr>
            }
        </tbody>
    </table>

<script>
function budgetFilter() {
    let budget = $("#budget").val();
    if (budget != "") {
        $.get("../Movies/App?budget=" + budget, function (response) {
        })
            .fail(function () {
                $("#budgetValidation").html("No films match your budget")
            });
    }
    else {
        $("#budgetValidation").html("Please enter a budget");
    }
 </script>

Controller:

        public async Task<IActionResult> App(decimal budget)
        {
            var movie = await _context.Movies.Where(m => m.Price <= 
            budget).ToListAsync();
            if (movie == null)
            {
                return NotFound();
            }
            return View(movie);
        }

I've debugged the controller and know it's working as intended. My understanding is that clicking budgetSubmit fires budgetFilter, which calls the App action method in the controller, which filters the movies model, then renders the same App view, but with the model I need to populate the table. It does work if I navigate directly to a url like "localhost:xxxx/Movies/App?budget=20". But not through the button click.

I understand I don't actually need to render the page all over again, but I don't see why the way I did it doesn't work and want to figure it out before moving on. How would you: 1. Do it the way I tried to do it, correctly, and 2. Do it a better way.

Thanks.

1
  • 2
    You are doing an ajax call. The ajax call will return your view inside the response variable, but you are currently not using it, so you could update your view there. Or you could include your budget in the viewmodel, and call your action using the default behavior of the submit button, by using the form taghelper. Commented Aug 15, 2019 at 12:31

2 Answers 2

2

Your best bet might be to return a partial view from your controller

public async Task<IActionResult> App(decimal budget)
    {
        var movie = await _context.Movies.Where(m => m.Price <= 
        budget).ToListAsync();
        if (movie == null)
        {
            return NotFound();
        }
        return PartialView(movie);
    }

Port the dynamic bit of your view out into a partial

<div id="budget"> 
  <table class="table" id="budgetTable">
   ...
  </table>
</div>

In the callback of your ajax

    $.get("../Movies/App?budget=" + budget, function (response) {
       $("#budget").html(response);
    })

This is sensible if you'd like fresh data upon each request. If you just want to return the full payload on the first call and filter client side I'd suggest looking at this

Sign up to request clarification or add additional context in comments.

Comments

1
  1. The simpliest way is just redirrect on url with budget value. Perfect works for pet\home projects.
<script>
    function budgetFilter() {
        let budget = $("#budget").val();
        if (budget != "") {
            window.location.href = `/Home/App?budget=${budget}`;
        } else {
            $("#budgetValidation").html("Please enter a budget");
        }
    }
</script>
  1. The right way is do the same things as it does guys from Microsoft: https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.