Sunday, July 27, 2014

Step by step how to create a Rich Form with the Twitter Bootstrap Widgets in MVC


Using the Twitter Bootstrap you can create elegant & responsive Rich Forms in MVC . All that's required is to bind the MVC Model to the open source Twitter Bootstrap widgets. 

The Twitter Bootstrap includes a lot of wigets and plugins to bring to your web page, with excellent responsiveness and elegant design, becoming the more widely used and popular CSS3 open source framework.

First of all, we'll need the Twitter Bootstrap CSS3 and JavaScript files. You can have  the Twitter Bootstrap installed in your MVC app in a few steps, as described   in this tutorial .

In just 15 minutes we'll build a responsive Rich Form made up of Widgets from the Twitter Bootstrap :




The Twitter Bootstrap can be reached  at the Bootstrap official website : Bootstrap :




First add to your web page the CSS and the .js jQuery files :







BUILDING A TWITTER BOOTSTRAP RICH FORM


In order to apply the Twitter Bootstrap to all TextBoxes in your application, the coolest way is to modify the Display and Editor Templates, located at "Views/Shared/DisplayTemplates/<type>.cshtml"  or "Views/Shared/EditorTemplates/<type>.cshtml" .
You can define custom templates overriding the default templates by creating your custom editor or display templates into the path above.
In our example, we modify the Editor Template to attach an Twitter Bootstrap class:



@model string

@Html.TextBox(@"",Model != null ? Model.Trim() : String.Empty  , new { @class="form-control" } )




We'll build a Rich Form for a Message creation, therefore we'll add some Data Annotations to our Model, as follows:





public class Message
    {
        public int ID { get; set; }
        [Required]
        public string To { get; set; }
        [Required]        
        public string Sender { get; set; }
        [Required(AllowEmptyStrings = false)]
        [StringLength(100, MinimumLength = 5)]
        public string Title { get; set; }
        public string Contents { get; set; }
    }


As you see, we just set some fields as "Required", and one of them will have a minimal length.
Then scaffold a strongly typed View for the Create Action method:



And customize it adding the Twitter Bootstrap classes as follows:
1) Add a Bootstrap Panel to holds the Form:

<div class="panel panel-default">
    <div class="panel-heading">
        <h2 class="text-muted">Create New Message</h2>
    </div>
    <div class="panel-body text-muted">

2) Arrange the Form controls according to the Bootstrap Layout Grid (12 columns) using the classes:

<div class="col-xs-6">

3) Locate the Validation Messages together at the end of the Form, and add them the Bootstrap class "new { @class = "alert alert-warning" }":

 <p>@Html.ValidationMessageFor(model => model.To, 
                                "Please enter the Email where to send the message", new { @class = "alert alert-warning" })
         @Html.ValidationMessageFor(model => model.Sender, 
                                "The Sender field is mandatory", new { @class = "alert alert-warning" })
                        </p>
                        <br />
    <p>@Html.ValidationMessageFor(model => model.Title, 
                                "Do you want to send a message without Title?", new { @class = "alert alert-warning" })
          @Html.ValidationMessageFor(model => model.Contents, 
                                null, new { @class = "alert alert-warning" })
                        </p>

4) Customize the Send button:

 <div class="btn-msg col-md-12">
                            <input class="btn btn-default" type="submit" value="Send Message" /><br />
                            <br />
  </div>

5) Add a DropDownList binded to some field as follows:

<div class="col-xs-6">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.To)
                        </div>
                        <div class="editor-field">                            
                            @Html.DropDownListFor(model => model.To, null, null, 
                                   new { @class = "form-control"})
                        </div>
                    </div>



Because the DropDownList  received a "null" parameter as data source, the MVC will automatically  search for a "model.To" List<> at the Model. We add also the Bootstrap class to customize the control. Notice that we wrote "@class", because "class" is a reserved word of C#, and we shouldn't use it.



6) Then we add an Email TextBox, but instead of declaring it as Email at the Model using Data Annotations, we declare it here, to prove that it's possible but not advisable (business logic MUST be placed at the Model) :

<div class="col-xs-6">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Sender)
                        </div>
                        <div class="editor-field">
                            @Html.TextBox("Sender", "", new { @class = "form-control", 
                                    placeholder = "Type your email here", type = "email" })

                        </div>
                    </div>




7) Then we add two more fields:
<div class="col-xs-12">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Title)
                        </div>
                        <div class="editor-field">
                            @Html.TextBox("Title", null, new { @class = "form-control" })

                        </div>
                    </div>
                    <div class="col-xs-12">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.Contents)

                        </div>
                        <div class="editor-field">
                            @Html.TextArea("Contents", "", new { @class = "form-control", 
                                    placeholder = "Here goes your message text" })

                        </div>
                    </div>

8) We add also the Bootstrap Checkbox:

<div class="col-xs-4">

                        <div class="checkbox">
                            <label>
                                <input type="checkbox" value="">
                                Checkbox one
                            </label>
                        </div>
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" value="">
                                Checkbox two
                            </label>
                        </div>
                        <div class="checkbox disabled">
                            <label>
                                <input type="checkbox" value="" disabled>
                                Checkbox three is disabled
                            </label>
                        </div>
                    </div>




9) And finally the Bootstrap RadioButtons:

<div class="radio">
                            <label>
                                <input type="radio" name="optionsRadios" id="optionsRadios1" value="option1" checked>
                                Radio button one
                            </label>
                        </div>
                        <div class="radio">
                            <label>
                                <input type="radio" name="optionsRadios" id="optionsRadios2" value="option2">
                                Radio button two
                            </label>
                        </div>
                        <div class="radio disabled">
                            <label>
                                <input type="radio" name="optionsRadios" id="optionsRadios3" value="option3" disabled>
                                Radio button three is disabled
                            </label>
                        </div>




10) I also customized the "Back to list" link:


<div>
    @Html.ActionLink("Back to List", "Index", null, new { @class = "btn btn-default" })
</div>

11) MAKE SURE you brought the jquery.unobtrusive and the jquery.validate javascript files:

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

The above Bootstrap markup is available at the Twitter Bootstrap website. You could also go to the Bootstrap website and copy the Widgets markup, then paste it inside your MVC View:





Then , add to the Controller the code to populate the Select List:




public ActionResult Create()
        {
            SortedDictionary<int, string> dict = new SortedDictionary<int, string>() {
                { 0, "The Professor" }, 
                { 1, "Philip J. Fry" }, 
                { 2, "Bender Rodriguez" }, 
                { 3, "Turanga Leela" }, 
                { 4, "Nibbler" } 
            };

            List<SelectListItem> options = new List<SelectListItem>();
            //  important! : "Value" must be "" !!!! (else, the "Required" data annotation won't work) : 
            options.Add(new SelectListItem { Value = "", Text = "Select an Email from the List" });
            foreach (var option in dict)
            {
                options.Add(new SelectListItem { Value = option.Key.ToString(), Text = option.Value });
            }
            ViewBag.To = options;
            return View();
        }

Save & refresh the web page. If you try to send the Web Form with the empty fields, you will get the Bootstrap Alerts warning you:


As you fill the fields, the Alerts go and disappear:



Finally, you will succeed sending the Form, and will be redirected to the Messages list:





That's all!!  Here we've learned how to create a Rich Form with the Twitter Bootstrap Widgets in MVC .

Happy programming....
        By Carmel Schvartzman
עריכה: כרמל שוורצמן