4

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;
    });
});
4
  • First remove contentType: "application/json; charset=utf-8",. And suggest you just use <a href="#" id="find">Find</a> rather than the helper (there is no point in adding the rote values etc) and the use $('#find').click() { Commented Sep 22, 2015 at 22:26
  • @StephenMuecke right but in your case you can just write evt.preventDefault(); before $.ajax and i gess it will work Commented Sep 22, 2015 at 22:28
  • @teovankot, OP already has return false; at the end of the script, but clearly the script is not running if it doing a redirect. Commented Sep 22, 2015 at 22:29
  • @StephenMuecke ok, my bad =) Commented Sep 22, 2015 at 22:30

1 Answer 1

1

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

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

2 Comments

Thanks so much! I will test this in the morning and update with / as answer
Works perfectly. The error: param is in the wrong section though. Thanks for the help!

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.