Juan M
Juan M

Reputation: 4503

Razor Mvc 3 + Jquery autocomplete issue

Helllo everyone,

I'm trying to code a simple registration form with Razor mvc3, using jquery autocomplete to fill city, state info from a database. The razor view uses form validation, and jquery populates textbox info. However, when passing data from said textbox to the controller, value is always null.

Textbox in View:

<input data-autocomplete="@Url.Action("AutoCompleteCity", "Search")"  class="form-control" placeholder="Enter City" name="city" id="city" />  

I also tried this alternative, to no avail:

@Html.TextBoxFor(u => u.city, new { @class="form-control", @placeholder="Enter city"})

Controller (registration.city is always null):

if (registration.city == null) ModelState.AddModelError("", "Must select City.");

Jquery Autocomplete:

$("#city").
        autocomplete({
        source: function (request, response) {
            $.ajax({    
                url: serviceURL,
                type: "POST",
                dataType: "json",
                data: { term: request.term },
                success: function (data) {
                    $("#targetDiv").append($("<ul id='targetUL' class='list-group'></ul>"));
                    //Removing previously added li elements to the list.
                    $("#targetUL").find("li").empty();

                    $.each(data, function (i, value) {
                        //On click of li element we are calling a method.                        
                        $("#targetUL").append($("<li class='list-group-item' onclick='javascript:addText(this)'>" + value.city + ", " + value.state + "</li>"));
                    });
                }
            })
        },

Any help will be greatly appreciated. I'm kind of new to Razor so probably I must be missing something. Thanks!!

EDIT - CONTROLLER CODE:

 [HttpPost]
        public ActionResult register(Models.UserForm registration)
        {                
            if (registration.email != null && registration.email.Length > Constants.MAX_MAIL_SIZE) ModelState.AddModelError("longUsername", "Username is too long");
            if (registration.email != null && !registration.email.Contains('@')) ModelState.AddModelError("wrongEmail", "Email is not valid.");
            if (registration.email == null || registration.email.Trim().Length == 0) ModelState.AddModelError("", "Name cannot be blank.");

            if (registration.password != null && registration.password.Length > Constants.MAX_PASS_SIZE) ModelState.AddModelError("", "Password is too long.");
            if (registration.password == null || registracion.contrasenia.Trim().Length == 0) ModelState.AddModelError("", "Password cannot be blank.");

            if (registration.name != null && registration.name.Length > Constantes.MAX_NOMBRE_SIZE) ModelState.AddModelError("", "Name is too long.");
            if (registration.name == null || registration.name.Trim().Length == 0) ModelState.AddModelError("", "Name cannot be blank.");

            if (registration.city == null) ModelState.AddModelError("", "Must Select City.");
            if (!db.validateExistingUser(registration.email)) ModelState.AddModelError("", "User already exists.");
            if (!ModelState.IsValid)
            {
                return View();
            }
            else
            {
                Usuario u = db.registerUser(registracion);
                Session["User"] = u;
                return View("Index");
            }
        }

Upvotes: 1

Views: 763

Answers (2)

Juan M
Juan M

Reputation: 4503

After searching quite a bit, I came up with a solution

View:

 <div class="editor-field">

      @Html.TextBoxFor(u => u.city.city, new { @class="form-control", @placeholder="Enter Your City"})
      <div id="targetDiv">                                 
      </div>                                
     @Html.HiddenFor(u => u.city.cityId)
     @Html.HiddenFor(u => u.city.state, new { Value = "" })                                       
     <br />
 </div>

Using the razor syntax to pass the ID's i need in the hidden inputs (Thanks @ben-jones for the suggestion).

I also made some adjustments to the Jquery Ajax method, making use of the data-* Attributes

$("#city_city").
        autocomplete({
        source: function (request, response) {
            $.ajax({    
                url: serviceURL,
                type: "POST",
                dataType: "json",
                async: false,
                data: { term: request.term },
                success: function (data) {
                    $("#targetDiv").append($("<ul id='targetUL' class='list-group'></ul>"));
                    //Removing previously added li elements to the list.
                    $("#targetUL").find("li").empty();

                    $.each(data, function (i, value) {
                        //On click of li element we are calling a method.                        
                        $("#targetUL").append($("<li class='list-group-item' onclick='javascript:addText(this)' value='" + value.cityId+ "' data-city='" + value.city+ "' data-state='" + value.state+ "' >" + value.city+ ", " + value.state+ "</li>"));
                    });
                }
            })
        },
        minLength: 3,
        delay: 200,
        messages: {
            noResults: "", results: ""
        }
        }).keyup(function (e) {

            $("#targetUL").empty();

            $("#city_city").autocomplete().term = null;            
        });

});


function addText(e) {
    var text= e.innerText;   

    $("#city_city").removeClass("input-validation-error");
    //setting the value attribute of textbox with selected li element.
    $("#city_city").html(text);
    $("#city_city").val(text);

    $("#city_cityIdidLocalidad").val(e.value);
    $("#city_city").val(e.getAttribute("data-city"));
    $("#city_state").val(e.getAttribute("data-state"));


    //Removing the ul element once selected element is set to textbox.
    $("#targetUL").empty();
}

Upvotes: -1

Ben Jones
Ben Jones

Reputation: 699

Instead of using this

data-autocomplete="@Url.Action("AutoCompleteCity", "Search")"

try wrapping the element inside a form and then inside the form set a hidden field

<input type="hidden" value="" />

and then set the value in JQuery and submit it with the rest of the fields

Upvotes: 2

Related Questions