mustang00
mustang00

Reputation: 313

I want to disable or hide one or two textboxes based on a dropdownlist selection from my view page

I want to basically disable or hide an editable textbox based on a selection from my dropdown list. I have a Delivery view page with statuses that I have hard-coded onto the model, and I also have separate textboxes that allow me to select the date and time for each status. All of which are currently displayed on the form.

Based on the status which could either be "Dispatched", "Received", "Delayed", I want to disable or hide (whichever option is practical) the corresponding date and time textbox of the other statuses. So for example, if I select 'Dispatched', I want to disable or hide the delayed_date and delayed_time as well as received_date and received_time textboxes. This is so the user can focus on the textbox related to the status they have selected.

How would I go about doing the above? I have done a bit of research on this but I have no idea how to apply it to my situation. I'm fairly new to MVC so I'm looking for a simple easy-to understand method of doing this. Is there an alternative to using jQuery or Javascript? Thanks in advance!

Delivery Model:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace HealthHabitat.Models
{
    public enum Status
    {
        Delivered, Delayed, Dispatched
    }
    public class Delivery
    {

        public int DeliveryID { get; set; }
        [Display(Name = "Driver")]
        public string DriverID { get; set; }
        public Status Status { get; set; }

        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Comment { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date Dispatched")]
        public DateTime Dispatched_Date { get; set; }

        [DataType(DataType.Time)]
        [DisplayFormat(DataFormatString = "{0:HH:mm}", ApplyFormatInEditMode = true)]
        [Display(Name = "Time Dispatched")]
        public DateTime Dispatched_Time { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date Received")]
        public DateTime? Received_Date { get; set; }

        [DataType(DataType.Time)]
        [DisplayFormat(DataFormatString = "{0:HH:mm}", ApplyFormatInEditMode = true)]
        [Display(Name = "Time Received")]
        public DateTime? Received_Time { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date Delayed")]
        public DateTime? Delayed_Date { get; set; }

        [DataType(DataType.Time)]
        [DisplayFormat(DataFormatString = "{0:HH:mm}", ApplyFormatInEditMode = true)]
        [Display(Name = "Time Delayed")]
        public DateTime? Delayed_Time { get; set; }



        public virtual Driver Driver { get; set; }
        public virtual ICollection<Order> Orders { get; set; }
    }
}

Create Delivery View:

@model HealthHabitat.Models.Delivery

@{
    ViewBag.Title = "Create";
}



@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Delivery</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.DriverID, "DriverID", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("DriverID", null, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.DriverID, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Status, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EnumDropDownListFor(model => model.Status, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Status, "", new { @class = "text-danger" })
            </div>
        </div>

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

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

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

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

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

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

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

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-success" />
            </div>
        </div>
    </div>
}

<div>
    <a href="~/Delivery/Index" class="btn btn-primary">Back</a>
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Upvotes: 2

Views: 1624

Answers (1)

Nate Barbettini
Nate Barbettini

Reputation: 53640

Since (I presume) the dropdown can be changed without posting the form, a JavaScript solution will be best here. jQuery should make this pretty easy:

First, as @mahlatse suggested, add a data-attribute to all of the form-group divs that matches the enum values. Also, add some custom class name that you pick, like section:

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

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

... and so on. This will ensure we can accurately show and hide each group of divs easily. The section class will ensure we can refer to all of these divs as a group later, too. Next, find the HTML ID of the dropdown list (or assign one to it), and hook up a jQuery event handler:

$(document).ready(function() {
    $('#dropdown-id-here').change(function(data) {
        var selected = data.target.value;
        switchUi(selected);
    });
)};

.change() is jQuery's way of attaching code to the control's change event. The CSS selector #dropdown-id-here is how it knows which control to attach the code to. data.target.value is the string value of the selected dropdown option.

Next, a helper function:

function switchUi(selection) {
    $('div.section').filter('[data-attribute="' + selection + '"]').show();
    $('div.section').not('[data-attribute="' + selection + '"]').hide();
}

The first line selects all divs on the page with the section class and then finds only the ones that have data-attribute=<selected option value>. .show() ensures those divs are visible. The second line just inverts this logic and hides all divs that do not have the currently selected option as their data-attribute.

We also want it to fire this off on page load, so whatever initial selection the dropdown has is reflected on the page immediately. Add another line to $(document).ready:

$(document).ready(function() {
    ...

    switchUi($('#dropdown-id-here').val());
});

Here's a simple fiddle example: http://jsfiddle.net/9f6nqcvt/3/


Some further thoughts:

  • You'll need to control what value MVC assigns to the dropdown control's HTML id.
  • Make sure you aren't completely relying on the textboxes being hidden; include some simple server-side validation that ensures the user doesn't enter bad data.

Upvotes: 2

Related Questions