0

First of all, this post Cascading drop-downs in MVC 3 Razor view has been very helpful. I have used the initial syntax, and have gotten my cascading drop down to work. I have added more parameters to the functions that are called in my controller, to change the list contents. Here is a View that does NOT use the "plugin".

@model HolterManagementUI.Models.CrudUserViewModel
@{
ViewBag.Title = "Edit";
}
@Scripts.Render("~/bundles/jquery")
<script type="text/javascript">
$(function () {
    $('#SelectedDivisionID').change(function () {
        var selectedDivisionID = $(this).val();
        $.getJSON('@Url.Action("Regions")', { divisionId: selectedDivisionID, isActive: true }, function (regions) {
            var regionsSelect = $('#SelectedRegionID');
            regionsSelect.empty();
            $.each(regions, function (index, region) {
                regionsSelect.append(
                    $('<option/>')
                        .attr('value', region.ID)
                        .text(region.Description)
                );
            });
         var locationsSelect = $('#SelectedLocationID');
         locationsSelect.empty();
        });
    });

    $('#SelectedRegionID').change(function () {
        var selectedRegionID = $(this).val();
        $.getJSON('@Url.Action("Locations")', { regionId: selectedRegionID, isActive: true }, function (locations) {
            var locationsSelect = $('#SelectedLocationID');
            locationsSelect.empty();
            $.each(locations, function (index, location) {
                locationsSelect.append(
                    $('<option/>')
                        .attr('value', location.ID)
                        .text(location.Description)
                );
            });
        });
    });
});
</script>
<h2>Edit User</h2>
@using (Html.BeginForm())
{

<table>
<tr>
    <td>LanID</td>
    <td>
    @Html.HiddenFor(h => h.ID)
    @Html.EditorFor(h => h.LanID)</td>
</tr>
<tr>
    <td>Division</td>
    <td>
    @Html.DropDownListFor(h => h.SelectedDivisionID, new SelectList(Model.Divisions, "ID", "Description", Model.SelectedDivisionID.ToString()))
    </td>
</tr>
<tr>
    <td>Region</td>
    <td>
    @Html.DropDownListFor(h => h.SelectedRegionID,  new SelectList(Model.Regions, "ID", "Description", Model.SelectedRegionID.ToString()))
    </td>
</tr>
<tr>
    <td>Location</td>
    <td>
    @Html.DropDownListFor(h => h.SelectedLocationID,  new SelectList(Model.Locations, "ID", "Description", Model.SelectedLocationID.ToString()))
    </td>
</tr>
<tr>
    <td>Is Active</td>
    <td>@Html.EditorFor(h => h.IsActive)</td>
</tr>
</table>

<div class="buttongroup" align="left" style="margin-top: 50px">
    <input type="submit" name="submitButton" value="Save" />
    <button type="button" onclick="location.href='@Url.Action("List")'">Cancel</button>
</div>
}

What I am unsure how to do is how to add the JavaScript plugin in the re-factored part, and then how to modify it so I can pass more than one parameter. I have attempted to add the code into a separate JavaScript file in my project and include it, but then the "wiring" always breaks.

Here is my separate JavaScript file:

/*!
* DropDowns.js
* Script to manage Cascading of dropdowns
* 
* From stackoverflow.com
* https://stackoverflow.com/questions/4458970/cascading-drop-downs-in-mvc-3-razor-view
*/
(function ($) {
$.fn.cascade = function (options) {
    var defaults = {};
    var opts = $.extend(defaults, options);

    return this.each(function () {
        $(this).change(function () {
            var selectedValue = $(this).val();
            var params = {};
            params[opts.paramName] = selectedValue;
            $.getJSON(opts.url, params, function (items) {
                opts.childSelect.empty();
                $.each(items, function (index, item) {
                    opts.childSelect.append(
                        $('<option/>')
                            .attr('value', item.Id)
                            .text(item.Name)
                       );
                    });
                });
            });
        });
    };
})(jQuery);

Here is my view that is attempting to use the DropDowns.js file:

@model HolterManagementUI.Models.CrudUserViewModel
@{
ViewBag.Title = "Create";
}

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/scripts/DropDowns.js")

<script type="text/javascript">
$(function () {
    $('#SelectedDivisionID').cascade({
        url: '@Url.Action("Regions")',
        paramName: 'divisionId',
        childSelect: $('#SelectedRegionID')
    });

    $('#SelectedRegionID').cascade({
        url: '@Url.Action("Locations")',
        paramName: 'regionId',
        childSelect: $('#SelectedLocationID')
    });
});
</script>
<h2>Create a User</h2>
@using (Html.BeginForm())
{

<table>
<tr>
    <td>LanID</td>
    <td>
    @Html.HiddenFor(h => h.ID)
    @Html.EditorFor(h => h.LanID)</td>
</tr>
<tr>
    <td>Division</td>
    <td>
    @Html.DropDownListFor(h => h.SelectedDivisionID, new SelectList(Model.Divisions, "ID", "Description"))
    </td>
</tr>
<tr>
    <td>Region</td>
    <td>
    @Html.DropDownListFor(h => h.SelectedRegionID,  Enumerable.Empty<SelectListItem>())
    </td>
</tr>
<tr>
    <td>Location</td>
    <td>
    @Html.DropDownListFor(h => h.SelectedLocationID, Enumerable.Empty<SelectListItem>())
    </td>
</tr>
</table>

<div class="buttongroup" align="left" style="margin-top: 50px">
    <input type="submit" name="submitButton" value="Save" />
    <button type="button" onclick="location.href='@Url.Action("List")'">Cancel</button>
</div>
}

So, 1. How do I get the plugin code to work? 2. How can I add more parameters to the plugin method for cascade? 3. Is this worth doing?

Community
  • 1
  • 1
Jennifer S
  • 1,419
  • 1
  • 24
  • 43

1 Answers1

1

First, for your broken plugin, I think you are trying to render to script for the dropdown.js incorrectly as you are treating is like a bundle when I believe it is not part of your bundle based on your syntax:

Change:

@Scripts.Render("~/scripts/DropDowns.js")

To:

<script type="text/javascript" src="@Url.Content("~/Scripts/DropDown.js")"></script>

Second, it appears that your second parameter is hardcoded, why not pass it as part of the URL you are generating for the plugin to use?

$('#SelectedDivisionID').cascade({
        url: '@Url.Action("Regions", "Controller", new{isActive = true})',
        paramName: 'divisionId',
        childSelect: $('#SelectedRegionID')
    });

Third, if you are using this code in multiple places, then yes, absolutely it would be worth not having to write what you did your first code block over and over again. This reduces complexity, points of failure and should speed up deployment of cascading dropdowns going forward in your project.

Tommy
  • 39,592
  • 10
  • 90
  • 121