Using Data annotation in Model for DateTime - c#

I am using following code to popup calendar for date in my razor view
Model
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
[DataType(DataType.Date)]
public Nullable<System.DateTime> EndTime { get; set; }
View
<div class="form-group">
#Html.LabelFor(model => model.EndTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.EditorFor(model => model.EndTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EndTime, "", new { #class = "text-danger" })
</div>
</div>
Now I want to use DateTime instead of Date.What should be the DataFormat String?
My Try
Display(Name = "End Date Time")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}{1:HH/mm}")]
[DataType(DataType.DateTime)]
I am getting format exception?

Your EditorFor() method renders an input with type="date" because of the [DataType(DataType.Date)] attribute, which will generate the browsers HTML-5 datepicker (but this is only supported in Chrome and Edge).
To generate a HTML-5 datetimepicker, you need to render an input with type = "datetime-local" but there is no data annotation attribute for that. Instead you need to generate the type attribute yourself.
#Html.TextBoxFor(m => m.EndTime, "{0:s}", new { #type = "datetime-local", #class = "form-control" })
Note "{0:s}" is shortcut for "{0:yyyy-MM-ddTHH:mm:ss}" and will display the date and time in the browsers culture. Note also that you do not need your [DataType] attribute or the ApplyFormatInEditMode = true property in the [DisplayFormat] attribute since they apply only to EditorFor()

Related

Client-side validation of US currency

I have an ASP.Net MVC 5 web application and I need to accept user input of US currency. Some valid inputs might be:
100
$100.21
$ 1,234
$1,234.56
Invalid inputs might be:
10,12
1o0.21
My (simplified) model looks like:
public class Claim {
[DisplayName("$ Amount)]
[DataType(DataType.Currency)]
[Required]
[Range(0.0, 200000.0)]
public decimal? DollarAmount { get; set; }
}
My cshtml markup looks like:
#Html.LabelFor(model => model.DollarAmount, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-9">
#Html.EditorFor(model => model.DollarAmount, new { htmlAttributes = new { #class = "form-control margin-bottom" } })
#Html.ValidationMessageFor(model => model.DollarAmount, "", new { #class = "text-danger" })
</div>
I used this advice this advice to build a binder that converts user input to a decimal, but client-side validation won't let the user enter a dollar-sign or commas. What do I need to do to allow the user to enter valid currency values, but warns her if she enters an invalid value? I'd prefer to do as much validation on the client-side as possible.
You Might want to look at https://github.com/globalizejs/globalize#currency-module. Helps allot with this kind of stuff. As for your Question to be able to use the Dollar Symbol you would not be able to store this Value as a decimal format in the database, only as a string.
There are a few things you can do, Use bootstrap to place a Dollar symbol in front of your TextBox using input-group-addon. Not sure if it will work properly as i see you have set Margin-bottom on your Textbox, telling me you might not be using bootstrap form tags above.
You may want to look into AutoNumeric jQuery plugin, It's well-maintained and they've basically "thought of everything" I could want for currency.
// View
#Html.LabelFor(model => model.DollarAmount, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-9 input-group">
<span class="input-group-addon">$</span>
#Html.EditorFor(model => model.DollarAmount, new { htmlAttributes = new { #class = "form-control margin-bottom" } })
#Html.ValidationMessageFor(model => model.DollarAmount, "", new { #class = "text-danger" })
</div>
// Class
public class Claim {
[DisplayName("$ Amount")]
[DataType(DataType.Currency)]
// {0:C} Will show as currency {0:N} to show Numbers
[DisplayFormat(DataFormatString = "{0:C}", ApplyFormatInEditMode = true))]
[Required]
[Range(0.0, 200000.0)]
public decimal? DollarAmount { get; set; }
}
Another option is to have a hidden field with javascript that will duplicate the field from a string to decimal and that can be the one you submit like below.
// MODEL
public class Claim {
[DisplayName("$ Amount")]
[DataType(DataType.Currency)]
[Required]
[Range(0.0, 200000.0)]
public decimal? DollarAmount { get; set; }
}
// View
#Html.HiddenFor(model => model.DollarAmount, new { #id = "DollarAmount" })
#Html.LabelFor(model => model.DollarAmount, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-9 input-group">
<span class="input-group-addon">$</span>
<input id="DollarSave" type="text" name="DollarSave" pattern="^\$?([0-9]{1,3},([0-9]{3},)*[0-9]{3}|[0-9]+)(.[0-9][0-9])?$" title="You must enter in proper currency">
#Html.ValidationMessageFor(model => model.DollarAmount, "", new { #class = "text-danger" })
</div>
<script type="text/javascript">
jQuery(document).ready(function($){
$('#DollarSave').change(function(){
var sourceField = $("#DollarSave").val(); //source field key
$("#DollarAmount").val(sourceField); //destination field key
$("#DollarAmount").change(); //destination field key
});
});
</script>
Pool pro's answer was a great help in solving my problem but I couldn't get his input tag pattern to display a message. It worked in JSFiddles, but not in my Asp.Net view template. So, I did the pattern validation and message update in javascript. I also used a different regex. For completeness, I'm posting my solution here:
#Html.HiddenFor(model => model.DollarAmount, new { #id = "DollarAmount" })
#Html.LabelFor(model => model.DollarAmount, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-9">
<input id="DollarSave" type="text" name="DollarSave" class="form-control text-box single-line">
<p id="BadDollarSave" class="text-danger"></p>
</div>
<script type="text/javascript">
jQuery(document).ready(function($){
$('#DollarSave').on('blur', function () {
validateDollarSave();
});
function validateMoney(inputId) {
var errorMsg = '';
var currency = $('#DollarSave').val();
var good = currency.match(/^(\$|\$ )?[0-9]{1,3}(?:(,[0-9]{3})*|([0-9]{3})*)(?:(\.|\.[0-9]{2}))?$/);
if (!good) {
errorMsg = "$ Amount must be US currency";
} else {
var num = currency.replace(/[, $]/g, "");
$('#DollarAmount').val(num);
}
document.getElementById('BadDollarSave').innerHTML = errorMsg;
};
});
</script>

Display Datepicker in Editor onload instead of needing the user to pick

currently I have this datepicker which will hightlight today's date on the pop up calender but the editor for the date onLoad shows DD/MM/YYYY instead of aotopopulating it when the page loads. How do I solve this ?
This is how I display my datepicker in the html file:
<div class="form-group">
#Html.LabelFor(model => model.date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.date)
#Html.ValidationMessageFor(model => model.date)
</div>
</div>
And this is how I define it:
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
Your EditorFor() method is rendering your browsers HTML-5 implementation of a datepicker, which requires that the format be yyyy-MM-dd (ISO format).
Change the attribute to
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")
public DateTime date { get; set; }
which will display the date in the browsers culture
Alternatively you can use
#Html.TextBoxFor(m => m.date, "{0:yyyy-MM-dd}", new { #type = "date" })
if you do not want to change the format that will be used in a DisplayFor() method.
Note also that type="date" is only supported in Chrome and Edge

Foolproof required value based on Dropdown value [duplicate]

This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 7 years ago.
I have discovered the Foolproof library that seems very nice but I am having problems to put it working.
I want to create a required field only if the dropdown has the selected value = 7.
Simple Model:
[RequiredIf("LeadSource_Id","7", ErrorMessage = "Campo obrigatório")]
public string SourceDescription { get; set; }
[Display(Name = "Origem")]
public virtual int LeadSource_Id { get; set; }
The way I create the Dropdown in the Controller:
ViewBag.LeadSource_Id = new SelectList(db.LeadSources.ToList(), "Id", "Name");
The View:
<div class="form-group">
#Html.LabelFor(model => model.LeadSource_Id, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("LeadSource_Id", null, htmlAttributes: new { #class = "form-control ld-lead-source" })
#Html.ValidationMessageFor(model => model.LeadSource_Id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group collapse">
#Html.LabelFor(model => model.SourceDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SourceDescription, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SourceDescription, "", new { #class = "text-danger" })
</div>
</div>
When I try to see if the validation is working when I select the value 7, I get the error:
The ViewData item that has the key 'LeadSource_Id' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
EDIT:
The libraries I include are:
<script src="~/Scripts/jquery/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Scripts/jquery/jquery.validate.globalize.min.js"></script>
<script src="~/Scripts/mvcfoolproof.unobtrusive.min.js"></script>
The error occurs because the value ofViewBag.LeadSource_Id is null. Since you have set its value in the GET method, then presumably this error is occurring when you return the view in your POST method (which you have omitted) but have not reassigned the value. In addition you cannot give the ViewBag property the same name as your model property.
Change your controller code to (say)
ViewBag.LeadSourceList = new SelectList(db.LeadSources.ToList(), "Id", "Name");
and ensure this code appears in both the GET method and POST method is you return the view, and modify the view to
#Html.DropDownList("LeadSource_Id", IEnumerable<SelectListItem>ViewBag.LeadSourceList , { #class = "form-control" })
However the recommended approach is to use a view model containing a property public IEnumerable<SelectListItem> LeadSourceList { get; set;}

How can I put a datepicker with mvc5

I have this code:
<div class="form-group">
#*#Html.LabelFor(model => model.DT_AGENDAMENTO, htmlAttributes: new { #class = "control-label col-md-2" })*#
#Html.Label("Data de Agendamento", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10" id="datepicker">
#Html.EditorFor(model => model.DT_AGENDAMENTO, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DT_AGENDAMENTO, "", new { #class = "text-danger" })
</div>
</div>
And at the end of my view, I have:
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
$(document).ready(function(){
$(".datepicker").datepicker();
});
}
How can I do to put a Datepicker(jquery or other) on my textbox(razor)?
Debugging the page on dev tools of chrome, I have this error:
GET http://localhost:55839/bundles/jquery-ui 404 (Not Found)
I do not know how to do.
For up to date browsers, the best choice is adding these data attributes to related property in class difination:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
Then just use #Html.EditorFor for property in view.
For bundles error check your bundles/jquery-ui in App_Start > BundleConfig.cs . probably definition has errore

MVC DisplayFormat Date + Time

I'm trying to display the date in this format: yyyy-MM-dd HH:mm, but it doesn't work (of course yyyy-MM-dd works fine, problem is with time)
MODEL:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm}", ApplyFormatInEditMode = true)]
public DateTime eventstart { get; set; }
VIEW:
<div class="form-group">
#Html.LabelFor(model => model.eventstart, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.eventstart, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.eventstart, "", new { #class = "text-danger" })
</div>
</div>
I'm assuming that you're generating an input with type="date". There's going to be two issues to be aware of with that:
As #JonSkeet pointed out, if you want to work with date and time, then you need to use DataType.DateTime. That will cause the input to be rendered as type="datetime". With an input of type "date", any time component will be discarded at best or at worst will not allow the value to parsed correctly for the browser date control, which brings us to:
The HTML5 datetime input types ("datetime", "date", "time") require the value to be in ISO format, i.e. YYYY-MM-DDTHH:MM:SSZ. The browser control will display the date/time in the user's local format based on parsing the ISO-formatted date, but it must be given the value in ISO format, first. If it's not, then it treats it as null, and will show the input value as empty.
Change:
#Html.EditorFor(model => model.eventstart,
new { htmlAttributes = new { #class = "form-control" } })
To:
#Html.EditorFor(model => model.eventstart,
new { htmlAttributes = new { #class = "form-control", #type="date" } })
Sure it will work.

Categories