问题描述:

I am creating a list of partial views on my main view. The partial view uses cascade dropdown lists. The cascade dropdowns work well on the first row however when I add a second row and change the value on the first dropdown the 2 second ones also get change instead of he one in the row I am just updating.

I researched and know that it is because of my script is using the same tag for both of them and not being unique.

I started using Html.BeginCollectionItem() to get unique names on my dropdowns and modified my script to get the value of the hidden field and tie to the right dropdown but it is not working.

Any ideas how can I have unique ids in my script?

This is my partial view:

@model BudgetPortalMVC4.Models.NewBudgetModel

@using (Html.BeginCollectionItem(""))

{

<script type="text/jscript">

$(function () {

var value = document.getElementsByName(".index")[0].value;

$(document).on('change', "#["+value+"].SelectedCategory", function () {

$("#["+value+"].SelectedSubCategory").empty();

$.getJSON('@Url.Action("GetSubCategories")', { id: $(this).val() }, function (data) {

if (!data) {

return;

}

$("#["+value+"].SelectedSubCategory").append($('<option></option>').val('0').text('Select Item'));

$.each(data, function (index, item) {

$("#["+value+"].SelectedSubCategory").append($('<option></option>').val(item.Value).text(item.Text));

})

});

});

});

</script>

<table>

<tr>

<td>

<div>

@Html.LabelFor(m => m.SelectedCategory)

@Html.DropDownListFor(m => m.SelectedCategory, Model.CategoriesList, "Please select", new { @class = "SelectedCategory" })

@Html.ValidationMessageFor(m => m.SelectedCategory)

</div>

</td>

<td>

<div>

@Html.LabelFor(m => m.SelectedSubCategory)

@Html.DropDownListFor(m => m.SelectedSubCategory, Model.SubCategoriesList, "Please select", new { @class = "SelectedSubCategory" })

@Html.ValidationMessageFor(m => m.SelectedSubCategory)

</div>

</td>

</tr>

</table>

}

This is part of the code it generates when rendered:

<input type="hidden" name=".index" autocomplete="off" value="b6fadec7-eb7d-4ce2-a06c-79ef0597b8da" />

<table>

<tr>

<td>

<div>

<label for="">SelectedCategory</label>

<select class="SelectedCategory" data-val="true" data-val-number="The field SelectedCategory must be a number." name=[b6fadec7-eb7d-4ce2-a06c-79ef0597b8da].SelectedCategory"><option value="">Please select</option>

<option value="1">Groceries</option>

<option value="2">Travel</option>

</select>

<span class="field-validation-valid" data-valmsg-for="[b6fadec7-eb7d-4ce2-a06c-79ef0597b8da].SelectedCategory" data-valmsg replace="true"></span>

An this is the error my script is throwing when trying to make the tag unique:

Error: Syntax error, unrecognized expression: #[4eebf546-988d-44a0-aa4e-296c46273d54].SelectedCategory

throw new Error( "Syntax error, unrecognized expression: " + msg );

网友答案:

Scripts should never be in partials. Move the script to the main view (or layout) and use your elements class names in jQuery selectors.

You partial should be

@using (Html.BeginCollectionItem(""))
{
    <div class="item">
        <label>
            <span>@Html.DisplayNameFor(m => m.SelectedCategory)</span>
            @Html.DropDownListFor(m => m.SelectedCategory, Model.CategoriesList, "Please select", new { @class = "SelectedCategory" })
            @Html.ValidationMessageFor(m => m.SelectedCategory)
        </label>
        <label>
            <span>@Html.DisplayNameFor(m => m.SelectedSubCategory)</span>
            @Html.DropDownListFor(m => m.SelectedSubCategory, Model.SubCategoriesList, "Please select", new { @class = "SelectedSubCategory" })
             @Html.ValidationMessageFor(m => m.SelectedSubCategory)
        </label>
    </div>
}

Note that because your model is IEnumerable<T>, the HtmlHelper methods will not generate an id attribute oro your form controls, so if you want labels, they need to wrap the control.

Note also that even if id attributes were created (assumingyour model was an object containing a property for the collection), the HtmlHelper methods replace any [, ] and . characters with and underscore to prevent a conflict with jQuery selectors, so something like #[4eebf546-988d-44a0-aa4e-296c46273d54].SelectedCategory would never exist in the view.

Then change the script to

var url = '@Url.Action("GetSubCategories", "Budget")'; // Do not hard code your url's
$(document).on('change', '.SelectedCategory', function() {
    var subCategory = $(this).closest('.item').find('.SelectedSubCategory');
    subCategory.empty();
    $.getJSON(url, { id: $(this).val() }, function (data) {
        if (!data) {
            return;
        }
        subCategory.append($('<option></option>').val('').text('Please select')); // Do not give the option a value!
        $.each(data, function (index, item) {
            subCategory.append($('<option></option>').val(item.Value).text(item.Text));
        });
    });
});

Note you also replace $(document) with the closest ancestor that exists in the document when the page is first rendered (e.g. that might be $('form'))

相关阅读:
Top