Canvas
Canvas

Reputation: 5897

How can I use AJAX to filter my MVC results

I have a simple MVC controller which uses a function and returns a list of CardType. now in my view I just do a simple foreach loop and draw out each CardType that was return't, now I have filter textboxes on the view so they can input some text hit enter and the page will refresh will the new results. But I know I can use AJAX to do this, but i don't really have a clue on where to start or end :).

Here is my controller method

[HttpGet]
public ActionResult CardTypes(TypeSearchModel searchModel)
{
    var cs = new CardService();
    searchModel.CardTypes = cs.GetCardTypes(searchModel);
    return View(searchModel);
}

and here is my view

@model CardSite.Models.CardTypeSearchModel

@{
ViewBag.Title = "Card types";
}


    <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
    </div>
    <div class="navbar-collapse collapse">
        <ul class="nav navbar-nav">
            <li>@Html.ActionLink("Created new card type", "CreateCardType", "Card")</li>
        </ul>
    </div>


<div class="row">
<div class="col-md-4">
    <h2>Card types</h2>
    <p>
        Here is the list of card types
    </p>
</div>
</div>

@using (@Html.BeginForm("CardTypes", "Card", FormMethod.Get))
{
@Html.TextBoxFor(x => x.Name);
}
<table class="table">
<tr>
<th>
    @Html.DisplayNameFor(x => x.Name)
</th>
<th>
    View
</th>
</tr>

@foreach (var item in Model.CardTypes)
{
<tr>
<td>
        @Html.DisplayFor(m => item.Name)
</td>
<td>
    <a href="/Card/CardType/@item.Id">View</a>
</td>
</tr>
}

</table>

If anyone has any ideas or tutorials that can help me that would be wonderful.

--- update ---

Just a quick update, I have moved my table cshtml code to a new view, this is the script i have at the moment

<script type="text/javascript">
$(document).ready(
        $('#filter-card-types').click(function () {
            var url = "Card/CardTypesTable/" + @Model.Name
            $.get(url, function(data)
            {
                if(data)
                {
                    $("div").find("#card-types-table").append(data);
                }
            })
        })
    );
</script>

now this is doing something but not the correct thing, it is basically finding my div which is correct, but the data is gets is the same page it is on, so it kinda re-renders itself inside of the new div. Any idea on why my data is the same as the view it is on?

--- update ---

Here is my new javascript function

$.get("@Url.Action("CardTypesTable", "Card")", { Name : '@Model.Name'}, function(data)
            {
                var div = $('div').find("#card-types-table");
                div.empty();
                alert(data);
                $.each(data, function(items, item) {
                    div.append("Card type : " + item.Name);
                });
            })

this is working fine, but the problem I am having is the Name is never populated, even If i put something in my TextBox and click the filter button, any reasons why it isn't picking it up?

Upvotes: 1

Views: 8633

Answers (2)

Canvas
Canvas

Reputation: 5897

I have fixed it, by using this javascript function

$.get("@Url.Action("CardTypesTable", "Card")", { Name: $('#Name').val() }, function(data)
            {
                var div = $('div').find("#card-types-table");
                div.empty();
                var htmlText = "";

                $.each(data, function (items, item) {
                    htmlText += ("<tr>" +
                                "<td>" +
                                item.Name +
                                    "</td>" +
                                "<td>" +
                                    "<a href='/Card/CardType/" + item.Id + "'>View</a>" +
                                "</td>" +
                            "</tr>");
                });

                div.append("<table class=table>" +
                            "<tr>" +
                                "<th>" +
                                    "Name" +
                                "</th>" +
                                "<th>" +
                                    "View" +
                                "</th>" +
                            "</tr>"+
                            htmlText+
                            "</table>");
            })

It calls the controller function CardTypesTable which looks like this

public JsonResult CardTypesTable(CardTypeSearchModel searchModel)
    {
        var cs = new CardService();
        searchModel.CardTypes = cs.GetCardTypes(searchModel);
        return Json(searchModel.CardTypes, JsonRequestBehavior.AllowGet);
    }

this then returns the data, and then i use javascript to write out the html, i'm sure there is an easier way then " text " + but I can not remember off the top of my head. Hope this helps other people :)

P.S. searchModel.CardTypes is just a List and cardtypes is just a model

Upvotes: 0

Dmitry Sikorsky
Dmitry Sikorsky

Reputation: 1501

It is good idea to use same method for initial and filtered data. So the first you should do is to add string (for example) parameter 'filter' to your TypeSearchModel. Use this parameter and collect only filtered data if it is set, or initial data if it doesn't. Then I'm sure you don't want your ajax response with filtered data contains all page's HTML-markup. So the second you should do is to add condition:

if (this.Request.IsAjaxRequest())
{
    return PartialView("_ResultsOnlyWithoutLayout");
}

return View();

This will use default page's view (with layout template) for initial data and specified partial view for ajax requests.

Now you are ready to go. Add javascript handler to your filter onchange event (if it is select) or onkeyup (if it is text input) and make the $.get request to the same url but with added 'filter' parameter. You will receive html containing only filtered data without layout so you can simply replace existing data with new one (you should give data containing HTML-element some id to work with it).

For example you can do this in next way (javascript with jquery):

$("#yourContainer").load("/your-url?filter=" + $("#filter").val());

Or the same:

$.get(
    "/your-url?filter=" + $("#filter").val(),
    function (result) {
        $("#yourContainer").html(result);
    }
);

Hope this helps!

Upvotes: 4

Related Questions