creatiive
creatiive

Reputation: 1093

MVC / AJAX send data to controller and load response in same view

I have a page with three form fields (2 textbox, 1 dropdown), a submit button and a 'refresh' link. I want to be able to click the link and pass two form textbox values to a controller action, and get a list of values to populate the dropdown box. I do not want to submit the form at this stage.

At the moment, I have managed to call the controller action from the link click, but I cannot pass the two form field values in for some reason. Also, the return JSON just takes me to a new page instead of populating my dropdown list. Any pointers would be great as I am new to javascript and MVC. My code is below;

Controller

public ActionResult Find(AddressFormViewModel model)
{
    ...
    var temp = new List<OptionModel>();
    temp.Add(new OptionModel {Id = item.Id, Value = item.desc});
    return Json(temp, JsonRequestBehavior.AllowGet);
}

HTML

@Html.TextBoxFor(x => Model.HouseNameInput, new { id = "HouseNameInput" })
@Html.TextBoxFor(x => Model.PostCodeInput, new { id = "PostCodeInput" })
@Html.ActionLink("Find","Find", "Address", new { houseInput = Model.HouseNameInput, postcodeInput = Model.PostCodeInput }, new { htmlAttributes = new { @class = "Find" } })

@Html.DropDownListFor(x => Model.AddressOption, Enumerable.Empty<System.Web.Mvc.SelectListItem>(), "-- Loading Values --", new {id = "AddressOptions"})

And lastly, my Javascript method which is retrieving the data from the controller action but not populating the dropdown list (it displays the results in a new page). It is also not successfully sending the form values to the controller action.

    $(function () {
    $('.Find').click(function (evt) {
        $.ajax({
            type: 'POST',
            url: '@Url.Action("Find","AddressFormSurface")',
            cache: false,
            async: true,
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            data: {
                houseNameInput: $("#HouseNameInput").value,
                postCodeInput: $("#PostCodeInput").value
            },
            success: function (data) {
                if (data.exists) {
                    var ddl = $('#AddressOptions');
                    ddl.empty();

                    data.each(function () {
                        $(document.createElement('option'))
                            .attr('value', this.Id)
                            .text(this.Value)
                            .appendTo(ddl);
                    });
                }
            },
            error: function (req) {

            }
        });

        // we make sure to cancel the default action of the link
        // because we will be sending an AJAX call
        return false;
    });
});

Upvotes: 4

Views: 2523

Answers (1)

user3559349
user3559349

Reputation:

You have a number of errors in your script which will cause it to fail.

  1. You specify contentType: "application/json; charset=utf-8", but do not stringify the data (the option should be removed)
  2. You need to use .val() (not .value) to get the values of the inputs
  3. The data you receiving does not contain a property named exists so the if block where you append the options will never be hit

In addition it is unnecessary to generate your link using @Html.ActionLink() (your adding route values based on the initial values of the model). Instead just create it manually

<a href="#" id="find">Find</a>

and change the script to

var ddl = $('#AddressOptions'); // cache it
$('#find').click(function () { // change selector
    $.ajax({
        type: 'GET', // its a GET, not a POST
        url: '@Url.Action("Find","AddressFormSurface")', // see side note below
        cache: false,
        async: true,
        dataType: "json",
        data: {
            houseNameInput: $("#HouseNameInput").val(),
            postCodeInput: $("#PostCodeInput").val()
        },
        success: function (data) {
            if (!data) {
                // oops
                return;
            }
            ddl.empty();
            $.each(data, function(index, item) {
                $(document.createElement('option'))
                    .attr('value', item.Id)
                    .text(item.Value)
                    .appendTo(ddl);
                // or ddl.append($('<option></option>').text(item.Value).val(item.Id));
            });
        },
        error: function (req) {
            ....
        }
    }
});

Side note: Also check the name of the controller. Your Html.ActionLink() suggests its AddressController but your script is calling AddressFormSurfaceController

Upvotes: 1

Related Questions