MVC 4 Razor using Ajax forms to update a foreach loop

27,616

Solution 1

@VishalVaishya presents the right idea, but there's a simpler way, which doesn't involve custom javascript code: AjaxOptions has an UpdateTargetId property that the AJAX toolkit will interpret to mean you want the given target to be updated with the results sent back from the controller.

FindATeacher.cshtml:

@using (Ajax.BeginForm("FilterTeachers", "Home", new AjaxOptions { 
    HttpMethod = "Post", UpdateTargetId = "TeacherList" }))
{
    ...
}
<hr />
<div id="TeacherList">
    @Partial("TeacherList", Model.Teachers)
</div>

TeacherList.cshtml

@model IEnumerable<Teacher>
@foreach(var teacher in Model)
{
   ...
}

Controller action:

    [HttpPost]
    public ActionResult FilterTeachers(String teacherName, String instrumentID, String cityID)
    {
        Model.Teachers = TeacherService.GetTeacherList(teacherName, instrumentID, cityID);
        return PartialView("TeacherList", Model.Teachers);
    }

Solution 2

You can try following method:

Separate your foreach loop into another partial view. And load your partial view on filter / click event and pass filtered parameters to your controller-action.

JS change event code will be something like this:

var teacherName = ''; //get your selected teachername
var instrumentID = ''; //get your selected instrumentid
var cityID = ''; //get your selected city id

var url = '@Url.Action("FilterTeachers", "ControllerName", new { teacherName = "teacher-Name", instrumentID="instrument-ID", cityID="city-ID" })';

url = url.replace("teacher-Name", teacherName).replace("instrument-ID", instrumentID).replace("city-ID", cityID);

$('#result').load(url);
Share:
27,616
Keltanis
Author by

Keltanis

Updated on October 29, 2020

Comments

  • Keltanis
    Keltanis over 3 years

    Where to start...I can find similar things on the Internet as to how, but they never seem to work with my specific way of wanting to do something. I have tried with and without partial views with very little success.

    Quick rundown: I have a strongly-typed View with an Ajax form. underneath the form, I have a foreach loop that repeats a code block. I need to be able to update the code block from the forms choices (filters).

    Here's my View, 'FindATeacher.cshtml', as it currently stands (after trying many different ideas):

    @model Teachers.Models.OmniModel
    @{
        ViewBag.Title = "FindATeacher";
        Layout = "~/Views/Shared/_Layout.cshtml";
    
    }
    <h2>Find a Teacher</h2>
    @using (Ajax.BeginForm("FilterTeachers", "Home", new AjaxOptions { HttpMethod = "Post", OnSuccess = "onSuccess" }))
    {
        <div id="ContentFilter">
            <div class="filterLabels">
                <p>Search by Name</p>
                <p>Filter By Instrument</p>
                <p>Filter By City</p>
            </div>
            <div class="filterObjects">
                <p>
                    <input type="text" id="nameTXT" />
                    <button type="submit" id="findButton">find</button>
                </p>
                <p>@Html.DropDownList("InstrumentID", (SelectList)Model.Instruments, "-- Select an Instrument --", new { id = "instrumentDD" })</p>
                <p>@Html.DropDownList("CityID", (SelectList)Model.Cities, "-- Select a City --", new { id = "cityDD" })</p>
            </div>
        </div>
    }
    <hr />
    @foreach (var r in Model.Teachers)
    {
        <div id="ContentResults">
            <div id="avatar">
                <img src="i" />
            </div>
    
            <div id="demographics">
                <h6>@r.Teacher</h6>
                <strong>@r.StudioName</strong>
                <p><a href="#">@r.URL</a></p>
                <p>@r.StreetAddress</p>
                <p>@r.City, @r.AddressStateID @r.Zip</p>
                <p>@r.Phone</p>
                <p>@r.EmailAddress</p>
            </div>
            <div id="studioDetails">
                <p><strong>Instrument(s) Taught</strong></p>
                <p>
                    @{
        var instrumentString = r.Instruments.Aggregate("", (a, b) => a + b.Instrument + ", ");
        if (instrumentString.Length != 0)
        {
            instrumentString = instrumentString.Remove(instrumentString.LastIndexOf(","));
        }
                    }
                    @instrumentString
                </p>
                <br />
    
                @if (r.Information != "" && r.Information != null)
                {
                    <p><strong>Information</strong></p>
                    <p>@r.Information</p>
                }
            </div>
        </div>
    }
    

    Now here's my Controller. I get the results back correctly in the Controller, just not updating the code block:

    public ActionResult FindATeacher()
            {
                Model.Instruments = new SelectList(TeacherService.GetInstrumentList(0),"InstrumentID","Instrument");
                Model.Cities = new SelectList(TeacherService.GetCityList(),"CityID","City");
                Model.Teachers = TeacherService.GetTeacherList("", 0);
                return View(Model);
            }
    
            [HttpPost]
            public JsonResult FilterTeachers(String teacherName, String instrumentID, String cityID)
            {
                Model.Teachers = TeacherService.GetTeacherList("John", 0, 0);
                return Json(Model.Teachers);
            }
    

    Thanks.

  • Haritha
    Haritha over 10 years
    TeacherList.cshtml is a partial view isn't it? And in the controller it should be return PartialView("TeacherList", Model.Teachers); ?
  • StriplingWarrior
    StriplingWarrior over 10 years
    @Haritha: Yes, I fixed that. Thanks.
  • Keltanis
    Keltanis over 10 years
    Unfortunately, this did not work. When I click the send button, I do not get an error, BUT I do not get the results I should be getting either. Nothing changes.
  • Keltanis
    Keltanis over 10 years
    Given that the above does not seem to work, unless amother solution pops up, I will have to try this today.In the solution above, on initial creation, I have two entries. The controller for the partial returns One entry on the filter, but both entries continue to show. Hope this first solution Vishal wote works :-)
  • StriplingWarrior
    StriplingWarrior over 10 years
    @user1842909: Use your browser's dev tools to check the network traffic and the javascript console. Is the partial view getting rendered and returned in the AJAX call? Are there any errors getting logged to the console?
  • Vishal Vaishya
    Vishal Vaishya over 10 years
    @StriplingWarrior i didn't tried this but do the action parameters matches i mean posting 3 parameters from form works? or in action we should use Teachers model to catch it?
  • Keltanis
    Keltanis over 10 years
    Actually, my problem is me being a moron :-) In my controller, my partial view was misspelled. Works perfectly!
  • Keltanis
    Keltanis over 10 years
    Didn't try this one because Stripling's works great.
  • Veggivore
    Veggivore about 6 years
    Any chance someone could post an example of the Model used for this illustration?