0

I have view for showing Member details. Inside there is an EditorFor element which represents subjects taken by the member.

 @Html.EditorFor(m => m.Subject)

Inside the editor template there is a Html.DropDownListFor() which shows the selected subject and button to delete that subject

I am using an Html.DropDownListFor element as :

@Html.DropDownListFor(m => m.SubjectID, Enumerable.Empty<SelectListItem>(), "Select Subject", 
new { @class = "form-control subjects" }) 

The second parameter(source) is set empty since I want to load the source from an AJAX request; like below:

$.getJSON(url, function (response) {
         $.each(response.Subjects, function (index, item) { 
                $('.subjects').append($('<option></option>').text(item.Text).val(item.ID));
            });
         // code to fill other dropdowns
    });

Currently the html loads before the dropdowns are filled. So the values of all subject dropdowns are set to the default "Select Subject". Is there a way around this or is it the wrong approach?

Note: There are a number of dropdowns in this page. That's why I would prefer to load them an AJAX request and cache it instead of putting in viewModel and filling it for each request.

** EDIT **

In AJAX call, the action returns a json object containing dropdowns used across all pages. This action is decorated with [Output Cache] to avoid frequent trips to server. Changed the code in $.each to reflect this.

Shwrk
  • 173
  • 1
  • 11

2 Answers2

0

If your JSON tells you what option they have selected you can simply do the following after you have populated your dropdown:

$('.form-control.subjects').get(0).selectedIndex = [SELECTED_INDEX];

Where [SELECTED_INDEX] is the index of the element you want to select inside the dropdown.

0

You can initially assign the value of the property to a javascript variable, and use that to set the value of the selected option in the ajax callback after the options have been appended.

// Store initial value
var selectedId = @Html.Raw(Json.Encode(Model.Subject.SubjectID))
var subjects = $('.subjects'); // cache it

$.getJSON(url, function (response) {
    $.each(response, function (index, item) { 
        subjects.append($('<option></option>').text(item.Text).val(item.ID));
    });
    // Set selected option
    subjects.val(selectedId);
});

However its not clear why you are making an ajax call, unless you are generating cascading dropdownlists which does not appear to be the case. What you doing is basically saying to the client - here is some data, but I forgot to send what you need, so waste some more time and resources establishing another connection to get the rest of the data. And you are not caching anything despite what you think.

If on the other hand your Subject property is actually a collection of objects (in which case, it should be Subjects - plural), then the correct approach using an EditorTemplate is explained in Option 1 of this answer.


Note also if Subject is a collection, then the var selectedId = .. code above would need to be modified to generate an array of the SubjectID values, for example

var selectedIds = @Html.Raw(Json.Encode(Model.Subject.Select(x => x.SubjectID)))

and then the each dropdownlist value will need to be set in a loop

$.each(subjects, function(index, item) {
    $(this).val(selectedIds[index]);
});
  • thank you for the response. :) have updated the question. I will try as you suggested – Shwrk May 04 '18 at 14:34
  • Your update makes little sense. If you want to cache your options because they rarely change, the cache them using `MemoryCache` (and invalidate the cache if the data is updated). For a typical wrapper class, refer [this Gist](https://gist.github.com/stephenmuecke/f24ab8a940d61035f711429a530376a8) –  May 04 '18 at 23:22