I have a web page that dynamically creates components by rendering them through a RenderPartial Html Helper like this
Html.RenderPartial("_UploadStaticField", config);
Within the config object is a field called 'isUnderReview'. When this is set to true the components should be disabled by using the code below
//Single selection
<div class="editor-section">
<div class="label">
@Html.DisplayEditLabel(Model.Label, Model.Required.Value)
</div>
<div class="field large-text-field">
@Html.DropDownListFor(m => m.SelectedListOptionID, new SelectList(Model.ListOptions, "ID", "Name", Model.SelectedListOptionID).OrderBy(l => l.Value), new Dictionary<string, object>{
{"id", "staticField_" + Model.ID}})
</div>
</div>
<script>
$(document).ready(function () {
if ("@Model.IsUnderReview" == "True") {
document.getElementById("staticField_" + "@Model.ID").disabled = true;
}
});
</script>
and..
//Multiple selection
<div class="editor-section">
<div class="label">
@Html.DisplayEditLabel(Model.Label, Model.Required.Value)
</div>
<div class="field large-text-field">
@Html.ListBoxFor(x => x.SelectedRoles, filetypes, new { @class = "multiselectFileTypes" , id = "staticFieldM_" + Model.ID})
</div>
</div>
@Scripts.Render(BundleConfig.Scripts_MultiSelect)
<script>
$(document).ready(function () {
if ("@Model.IsUnderReview" == "True") {
document.getElementById("staticFieldM_" + "@Model.ID").disabled = true;
}
});
</script>
The code works to the point that the methods run but the components are still able to be used. Is there a way of cancelling any users selections which will serve as disabling as the values wont change?
Scripts should never be in partials (you potentially generating multiple inline scripts that may cause other problems, especially with the bundle). However a script is not even necessary for this, you can use a simple if
statement or conditional attributes to generate what you want.
When you say "but the components are still able to be used", I'm guessing that your using a plugin to generate controls as suggested by Scripts.Render(BundleConfig.Scripts_MultiSelect)
which will be hiding the original <select>
element and generating its own html which is why it still interactive.
But the next problem is that disabled controls do not post back a value, so the vales of SelectedListOptionID
and SelectedRoles
will be their default, possibly resulting in your app failing depending on the code in your POST method.
Move the @Scripts.Render()
into you view or layout, delete the scripts to disable the element and then change the partial to
@if(Model.IsUnderReview)
{
@Html.HiddenFor(m => m.SelectedListOptionID) // if you want the value to be posted
// add an element to display the Name associated with the SelectedListOptionID
// if necessary, for example your view model might include a property
// string SelectedListOptionName
}
else
{
@Html.DropDownListFor(m => m.SelectedListOptionID, new SelectList(Model.ListOptions, "ID", "Name").OrderBy(l => l.Value))
}
Side notes:
id
attribute (the
DropDownListFor()
method generates <select
id="SelectedListOptionID" ... >
SelectList
constructor
(Model.SelectedListOptionID
) - its ignored by the
DropDownListFor()
method. I also recommend your model contains an IEnumerable<SelectListItem> OptionsList
property and you populate that in the controller so that it can simply be @Html.DropDownListFor(m => m.SelectedListOptionID, Model.OptionsList)