0

I am wondering if there is a way to create multiple DropDownLists on the client side from one source in the model.

The background is I need to create a view that contains about 30 DropDownLists. The DropDownLists are identical to one another, and each contains about 400 entries. My model contains one

List<SelectListItem> StandardProductTypes

to hold all entries for each DropDownList.

Here is what is in my current view:

@for (int i = 0; i < Model.Mappings.Count; i++)
{
    @Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey,
                        new SelectList(Model.StandardProductTypes, "Value", "Text", Model.Mappings[i].SelectedStandardProductTypeKey))
}

As you can see, this is returning 30 x 400 = 12000 entries from the sever, and the page loads rather slowly.

All that is really required is only 400 entries transferred and they are replicated 30 times on the client side in the browser. Is there a way to achieve that? Any reference to reading materials or tutorials will be good.

Thanks in advance.

Nay

2 Answers 2

1

how about copy with jQuery?

$('#myDropDownlist1 option').clone().appendTo('#myDropDownlist2');
Sign up to request clarification or add additional context in comments.

Comments

0

Ok firstly you have no need to create a new SelectList for every DropDownList as the source. The DropDownListFor method just requires an IEnumerable<SelectListItem> as a source, which you already have (and the selected value is determined by the property value it is for normally, so you don't need to pass this in explicitly for the selected value.

Ie given "StandardProductTypes" is already IEnumerable<SelectListItem> you can simplify your DropDownListFor from

 @Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey,
                        new SelectList(Model.StandardProductTypes, "Value", "Text", Model.Mappings[i].SelectedStandardProductTypeKey))

To

 @Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey,
                        Model.StandardProductTypes)

Also I would generally NOT put stuff like a List<SelectListItem> in the model, because you don't need to pass it back after postback. Having it in the Viewbag is fine.

However that's just good practice, and besides the point, as the HTML here will still include all the options for all the dropdowns. TO solve your issue you want to return it only once, and then use some client side jQuery/javascript to replicate it

EG:

use

@Html.DropDownListFor(model => model.Mappings[i].SelectedStandardProductTypeKey, new List<SelectListItem>())
@Html.Hidden(String.Format("Mappings[{0}].SelectedStandardProductTypeKey_Initial",i), Model.Mappings[i].SelectedStandardProductTypeKey) 

in place of the dropdown (so you have the correct initial value)

Then a bit of script at the end to fill the dropdownlists:

<script>
var ddlVals= new Array();
@foreach(var item in Model.StandardProductTypes) // get all the select list items into a javascript array
{
   @Html.Raw(String.Format("ddlVals.push(['{0}','{1}']);", item.Key, item.Value))
}

$('input[type="select"][name$="SelectedStandardProductTypeKey"]').each(function()
{
   var initValue $("name='" + $(this).attr("name") + "_Initial'").val();
   foreach(var item in ddlVals)
   {
     var html = '<option value="' + item[0] + '"'
     if (item[0] == initValue){ html = html + ' selected="selected"'} 
     html = html + '>' + item[1] + '</option>';
     $(this).append(html);
   }
}

</script>

EDIT

May be quicker using the idea in Edi G's answer

But you'd still need to select the correct initial value.

So keep the hidden fields and dropdowns above, but instead of the previous script how about:

<!-- a template dropdownlist - hidden from view -->
@Html.DropdownList("ddlTemplate", Model.StandardProductTypes, new {id = "ddlTemplate", style="display:none;"})
<script>
$('input[type="select"][name$="SelectedStandardProductTypeKey"]').each(function()
    {
       $('#ddlTemplate option').clone().appendTo($(this));
       var initValue $("name='" + $(this).attr("name") + "_Initial'").val();
       $(this).val(initValue);
    }
</script>

EDIT 2

If you still find the page to be unresponsive when the javascript is populating the dropdowns after trying the script in the edit above then I have another possible solution.

You would basically need to populate each dropdown with a source as a new List<SelectListItem> - each containing just the single selected option.

Populate an array of values (as per the original script), but then instead of immediately populating all the dropdowns have some javascript that populates the remaining values from the array when you drop the dropdownlist for the first time.

That way you only load the full list of 400 items once, and client side javascript only needs to do work when you click a dropdown, rather than all 30 dropdowns at page load time.

3 Comments

Thank you @James S. Works fine. However, I get 'unreponsive script' warning. When I click 'continue', it completes successfully. Is there anything in the code that I could to so this warning box won't show up? Also, regarding what you wrote: "the selected value is determined by the property value it is for normally, so you don't need to pass this in explicitly for the selected value". I tried that just for curiosity, but doesn't work in my instance, i.e. if I don't specify the selected value explicitly, the drop down list is set to the first item.
@Nay - see the edit to my answer, which may be quicker! Also I generally use a List<SelectListItem> as the source for my dropdowns rather than a SelectList, and find so long as one of the SelectListItems has a value matching the property value that one is selected.
Thanks @James S. The pop up still shows, but I think I'm showing too much on one screen. Tried paging and it works fine. Thanks for your 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.