This tutorial will be very easy for most of you intermediate
developers, but I wanted to show bundle feature that is available in MVC 4 using
date picker example. I will also show how we can add datepicker in previous
versions of MVC.
There are few methods we can do it however I will show you
only 2.
First we have to add some references to jquery, jquery-ui
and styles. As I mention in mvc 4 we can use bundles which improve performance
and give us less headache in the future.
To access bundle configuration go to App_Start and open
BundleConfig.cs.
You can very easily add your own custom styles and scripts
to existing bundles. For instance you can MyCustomStyles.css to existing
bundle:
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css", "~/Content/MyCustomStyles.css"));
Open _Layout page and find at the bottom @Scripts.Render("~/bundles/jquery"). Cut it and paste
inside head – sounds creepy. Also add @Styles.Render("~/Content/themes/base/css") and @Scripts.Render("~/bundles/jqueryui"). This way we
included files we need to use datepicker.
Your code should like this:
@Styles.Render("~/Content/css")
@Styles.Render("~/Content/themes/base/css")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")
Using model for datepicker (preferred
method).
To
use this method we are going to create Discount model. Create a new class and
call it Discount.
public class Discount
{
public Discount()
{
dateFrom = DateTime.Now.Date;
dateTo = DateTime.Now.Date;
}
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime
dateFrom { get; set;
}
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime
dateTo { get; set;
}
public decimal
discountPercentage { get; set; }
public string
discountName { get; set;
}
}
We
are using simple constructor to define default date. Date are also formatted to
show only date.
Add
new controller and call it Date and add new View from the controller(you can
right click on the Action name and choose add View.
public ActionResult
Index()
{
return View(new Discount());
}
Open Index view from Date controller.
@model Components.Models.Discount
<script>
$(function () {
$("#dateFrom, #dateTo").datepicker();
});
</script>
<h2>
Date
picker test</h2>
<table>
<tr>
<td>@Html.EditorFor(m => m.dateFrom)
</td>
<td>@Html.EditorFor(m => m.dateTo)
</td>
</tr>
</table>
In view we added class for model (Components is the name of
the project, Models is the folder where we created Discount class).
As you can see we do not have to reference jquery here, as
it was already referenced in Layout. In previous MVC you would have to include
3 separate files inside layout, or on the individual page (not recommended).
It would look something like that:
<script src="../../Scripts/jquery-ui-1.8.20.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<link href="../../Content/themes/base/jquery.ui.datepicker.css"
rel="stylesheet"
type="text/css"
/>
In the old MVC version if you wanted to update jquery you
would have to manually change the version name to match your newest jquery,
where in MVC 4 system will automatically figure it out.
Check BundleConfig.cs file again:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
Adding date picker without model.
@{
ViewBag.Title = "Index";
}
@model Components.Models.Discount
<script>
$(function () {
$("#dateFrom, #dateTo, #datepickerNoModel").datepicker();
});
</script>
<h2>
Date
picker test</h2>
<table>
<tr>
<td>@Html.EditorFor(m => m.dateFrom)
</td>
<td>@Html.EditorFor(m => m.dateTo)
</td>
<td>
<input type="text" id="datepickerNoModel"
/>
</td>
</tr>
</table>
Main advantage using the model for
datepicker is that you can very easily pass data from view to controller, where in other case you would have to formcollection.
Calling the controller with model date
picker
@using(Html.BeginForm("SubmitDiscount", "Date", FormMethod.Post))
{
<table>
<tr>
<td>@Html.LabelFor(m=>m.discountName)</td>
<td>@Html.LabelFor(m=>m.dateFrom)</td>
<td>@Html.LabelFor(m=>m.dateTo)</td>
</tr>
<tr>
<td>@Html.TextBoxFor(m=>m.discountName)</td>
<td>@Html.EditorFor(m => m.dateFrom)
</td>
<td>@Html.EditorFor(m => m.dateTo)
</td>
</tr>
</table>
<input type="submit"
value="Apply
discount"/>
}
We have modified View a bit and
added new controller SubmitDiscount.
Run the application and go to date controller so
your path should something like that localhost:9930//Date, put a break point for debugger on SubmitDiscount method. You will see that the
fields we have submitted have been passed to controller via model.
Now let’s use form collection now
to pass date without using the model.
Modify controller:
Modify controller:
public ActionResult
SubmitDiscount(Discount model, FormCollection form)
{
var date = form["dateNoModel"];
DateTime convertDateFromString = DateTime.Parse(date);
return RedirectToAction("Index");
}
And view by replacing dateTo model with input.
@using(Html.BeginForm("SubmitDiscount", "Date", FormMethod.Post))
{
<table>
<tr>
<td>@Html.LabelFor(m=>m.discountName)</td>
<td>@Html.LabelFor(m=>m.dateFrom)</td>
<td>@Html.LabelFor(m=>m.dateTo)</td>
</tr>
<tr>
<td>@Html.TextBoxFor(m=>m.discountName)</td>
<td>@Html.EditorFor(m => m.dateFrom)
</td>
<td><input type="text" id ="dateTo"
name="dateNoModel"/>
</td>
</tr>
</table>
<input type="submit"
value="Apply
discount"/>
}
Run the application and debug the method again. Choose dateTo and
check your model and form.
As you can see it is faster and more reliable to use model with date
picker. All elements within the form are type of string so you will have to
convert them if necessary which is time consuming and can be avoided.
This comment has been removed by the author.
ReplyDeleteGood call on the use of razor helpers & models.
ReplyDeleteHere is a similar approach I've put together. This article is based on a sample application I'm working on which is ASP.NET MVC5 w/ the bootstrap template.
There is also some code hosted in my GitHub repo that can be used.
Goodd job
ReplyDelete