1

I have a MVC view with a model, where, when I select something from a drop down list, it does a JSON query to my controller, gets an updated list of items for a second drop down, and repopulates the 2nd drop down with new values. I do this, but building the <option value="5">Test</option><option value="13">Another</option>.... string, and then set the HTML of the 2nd drop down with that new code:

Javascript:

$(".cmbSubCategory").html(result.SubCategoryString);

Visually, this is working well. My UI updates nicely.

However, when I save, it seems it doesn't recognise the selected value of the second drop down, which is the one I built.

Once I rebuild a control, that was originally setup by a view model:

@Html.DropDownListFor(x => x.SubCategoryId, Model.SubCategories, new { @class = "cmbSubCategory form-control" })

.. can I no longer use the selected value in the model, when I do the 'post' back to my controller?

I notice that even after visually, the 2nd dropdown is populated with a few options, when I 'View Page Source', it just shows:

<select class="cmbSubCategory form-control" data-val="true" data-val-number="The field SubCategoryId must be a number." data-val-required="The SubCategoryId field is required." id="SubCategoryId" name="SubCategoryId"><option value="0">Select a Category</option>
</select>

No options.. But in the browser, it shows items...

Edit: Found the issue!

Althought I was populating the HTML and setting the 'Selected' value in the HTML, I wasn't setting the 'val' of the drop down list!

This now works:

if (result.Success == 'true') {
                    if (result.SubCategoryString != "") {
                        $('#cmbType').val(result.TransactionTypeId);
                        $('#cmbCategory').val(result.CategoryId);
                        $(".cmbSubCategory").html(result.SubCategoryString);
                        $(".cmbSubCategory").val(result.SubCategoryId);
                    }
                }

The last line is the key! $(".cmbSubCategory").val(result.SubCategoryId);

I thought building the HTML Selected option would have been enough - but you must also set the 'val' of the combo.

3
  • 1
    Please add your controller code and how you are populating a second drop down, via ajax? Commented Jan 10, 2014 at 9:51
  • 1
    Debug hint: Use 'inspect element' instead 'view page source'. See: stackoverflow.com/questions/8003070/… Commented Jan 10, 2014 at 9:53
  • Thanks! The debug has helped! When I generate the new SELECT, and set the selected value, I just add a 'SELECTED' word to the <Option> tag. However, when I manually select the value in the drop down, and then inspect, the 'SELECTED' isn't shown in the markup. Maybe I am supposed to set something else? Commented Jan 10, 2014 at 23:42

1 Answer 1

2

Ok, here is a working example.

Please note that the hardcoded values are just for demonstration purposes.

Model

    public class FooModel
    {
        public int CategoryId { get; set; }
        public int SubCategoryId { get; set; }
        public List<Category> Categories { get; set; }
        public List<SubCategory> SubCategories { get; set; }
    }

    public class Category
    {
        public int Id { get; set; }
        public string Description { get; set; }
    }

    public class SubCategory
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public int CategoryId { get; set; }
    }

Actions

   public ActionResult Ddl()
    {
        var model = new FooModel();
        var categories = new List<Category>();
        var subCategories = new List<SubCategory>();

        // Read from db
        categories.Add(new Category { Id = 1, Description = "Cat 1" });
        categories.Add(new Category { Id = 2, Description = "Cat 2" });
        subCategories.Add(new SubCategory { Id = 1, Description = "Sub-Cat 1", CategoryId = 1 });
        subCategories.Add(new SubCategory { Id = 2, Description = "Sub-Cat 2", CategoryId = 2 });

        model.Categories = categories;
        model.SubCategories = subCategories.Where(s => s.Id == 1).ToList();

        // initially set selected
        model.CategoryId = 1;
        model.SubCategoryId = 1;

        return View(model);
    }

    [HttpPost]
    public ActionResult Ddl(FooModel model)
    {
        var subCategoryId = model.SubCategoryId;

        // Send categories back to model etc
        ...

        return View(model);
    }

Json Action

This filters on the selected id

    [HttpGet]
    public ActionResult GetSubCategories(int id)
    {
        var subCategories = new List<SubCategory>();
        subCategories.Add(new SubCategory { Id = 1, Description = "Sub-Cat 1", CategoryId = 1 });
        subCategories.Add(new SubCategory { Id = 2, Description = "Sub-Cat 2", CategoryId = 2 });
        var filteredCategories = subCategories.Where(s => s.Id == id).ToList();
        return Json(filteredCategories, JsonRequestBehavior.AllowGet);
    }

View

This simply sets an onchange event for the category which loads the options into the sub category list.

@model FooModel

@using (Html.BeginForm())
{
    @Html.DropDownListFor(m => m.CategoryId, new SelectList(Model.Categories.AsEnumerable(), "Id", "Description"))
    @Html.DropDownListFor(m => m.SubCategoryId,new SelectList(Model.SubCategories.AsEnumerable(), "Id", "Description"))
    <input type="submit" value="submit" />
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script>
    var getsubCategoryUrl = '@Url.Action("GetSubCategories")';
    $(function () {

        $('#CategoryId').change(function () {
            var selectedCategory = $('#CategoryId').val();
            if (selectedCategory != null) {
                $.getJSON(getsubCategoryUrl, { id: selectedCategory }, function (subs) {

                    var subSelect = $('#SubCategoryId');
                    subSelect.empty();

                    $.each(subs, function (index, sub) {
                        subSelect.append($('<option/>', {
                            value: sub.Id,
                            text: sub.Description
                        }));
                    });

                });
            }
        });

    });
</script>

As the sub category list is picked up by the model binder your selected option will be set in your post.

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

5 Comments

I'm unsure where this code fits into my current script. Can you assist? Yes, the field names are 'Id' and 'Description', but I also need to set the Selected value. I do that like this in my Controller at the moment:reply += string.Format("<Option value='{0}' {2}>{1}</option>", item.Id, item.Description, item.Id == tp.DefaultSubCategoryId ? "Selected" : "");
Hi, I can. I'm not at a PC yet but when I get on I will post an example. The controller returns json objects projected using linq.
Sorry, I see you solved it now. I can still post the example later if u need it. Just let me know if u do.
An example would be great. Your way seems better.
Ok, I will sort one now for you.

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.