EbertB
EbertB

Reputation: 93

How to make @Html.EditorFor readonly depending on Drop List

I want to make @Html.EditorFor read only until a certain drop down selection is made. So my drop down looks like this:

List<SelectListItem> listDepartments = new List<SelectListItem>();
listDepartments.Add(new SelectListItem
                     {
                         Text = "Sales",
                         Value = "Sales"
                     });
listDepartments.Add(new SelectListItem
                     {
                         Text = "Staff",
                         Value = "Staff",
                         Selected = true
                     });

and I want to make the @Html.EditorFor read only unless the dropdown list is Staff. Is that hard to do?

<div class="form-group">
    @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
    </div>
</div>

Upvotes: 0

Views: 475

Answers (2)

Georg Patscheider
Georg Patscheider

Reputation: 9463

You have to use Javascript to react to client browser events like a change of the entry selected in the dropdown. The following code uses jQuery to achieve this.

1) You will need a handle on the dropdown so you can listen to its change event. Here I use the @Html.IdFor() helper to get the Ids of the input elements that were generated by@Html.DropDownListFor()/ @Html.EditorFor(). Then I create jQuery selectors based on these Ids.

2) Register an JS event handler for the change event of the dropdown.

3) Toggle the readonly attribute of the text input depending on the value selected in the dropdown.

In your cshtml page:

<script type="text/javascript">
$(document).ready(function () {

   // 1) get selectors
   var dropDownSelector = $('#@Html.IdFor(m => m.listDepartments)');
   var textBoxSelector = $('#@Html.IdFor(m => m.Description)');

   // 2) listen to change event
   dropDownSelector.on('change', function() {

       // 3) toggle readonly attribute
       var selectedValue = dropDownSelector.val();
       if (selectedValue === 'Staff') {
           textBoxSelector.removeAttr('readonly');
       }
       else {
           textBoxSelector.attr('readonly', 'readonly');
           // maybe you also want to clear the text input?
           // textBoxSelector.val('');
       }
   });
});
</script>

Upvotes: 2

Sean T
Sean T

Reputation: 2494

How about something like below with a ternary operator ? ?

@{
    var isReadonly = Model.Description == "Staff"
}

<div class="form-group">
    @Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Description, (isReadonly 
                              ? new {  @class = "form-control", @readonly = "readonly" } 
                              : new { @class = "form-control" } 
                              ))
        @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
    </div>
</div>

I prefer to do my selects without a helper as I find them a bit clumsy so something like...

@{
    var isReadonly = Model.Description == "Staff"
}

<div class="form-group">
    @Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
    <div class="col-md-10">
      <select name="Description" class="form-control @(isReadonly ? "readonly" : "")">
          <option value="" selected="selected" disabled="disabled">Please select...</option>
          @foreach (var option in Model.listDepartments)
          {
              <option value="@option.Value" @(option.Value == Model.Description ? "selected='selected'" : "")>@option.Text</option>
          }
      </select>
        @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
    </div>
</div>

Upvotes: 0

Related Questions