I need to validate a date field which is being entered by a user via a visualforce page.
The format my code expects is "yyyy-MM-dd".
What is the best way to handle this in apex. I have done similar stuff in Java before using certain standard classes which are not available in Apex like SimpleDateFormat for example.
Now I can check if the "format" is correct using a regular expression. But I must also prevent users from entering "9999-99-99" which satisfies the format. I am hoping Salesforce has a good built-in solution.
Thanks,
Calvin
You might try what I call control spoofing. I basically create an empty sObject that has a date field like a Task object (or something similarly light weight). On the screen I display the input for the task date which will render the native date field. Doing this you get salesforce to validate the date input from the user, and the user get's the nice calendar popup as well.
Here is a sample of what that would look like in the controller
public class MyController {
public Task DateInput {get;set;}
public MyController() {
DateInput = new Task();
}
public void save() {
Date dInputDate = DateInput.ActivityDate;
//Format Date
DateTime dtValue = DateTime.newInstance(dInputDate.year(), dInputDate.month(), dInputDate.day());
string sFormattedDate = dtValue.format('yyyy-MM-dd');
}
}
Here is what the Page would look like
<apex:page controller="MyController">
<apex:form>
<apex:pageBlock>
<apex:pageBlockSection>
<apex:pageBlockSectionItem>
<apex:outputLabel for="inputDate" value="My Date"/>
<apex:inputField value="{!DateInput.ActivityDate}" />
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
You notice the formatting that I did in the save method. You can't use format on Date but you can on DateTime so I just convert the Date to a DateTime and then use the format method to format my date.
Guys I managed to solve my problem because it was a little unique anyways.
So I used a regex to validate the format of the date being entered to ensure it is in yyyy-MM-dd format.
The I used Date.valueOf
This built in method always takes a date in the form of yyyy-MM-dd. It throws an exception if that has a bad value like 9999-99-99 etc....I display the exception's message to the user using e.getMessage() to complete my validation of the date fields.
Related
How can I make same format of date between server and client. My server's date format is yyyy/mm/dd. But the client's date format is dd/mm/yyyy. When the model post to server, the system cannot bind date from client form data because of client's date format. Please see sample code below.
In Controller
Function TestDateFormat() As ActionResult
Dim testDateFormatVM As New TestDateFormatVM
testDateFormatVM.FormatDate = New Date(1989, 8, 22)
Return View(testDateFormatVM)
End Function
In Model
Public Class TestDateFormatVM
Public Property FormatDate As DateTime
End Class
In View
#ModelType ListTest.TestDateFormatVM
#Code
ViewData("Title") = "TestDateFormat"
End Code
<h2>TestDateFormat</h2>
#Using Html.BeginForm("Display", "Home")
#Html.TextBoxFor(Function(item) item.FormatDate)
#Html.HiddenFor(Function(item) item.FormatDate)
#<input type="submit" value="SUBMIT" />
End Using
Before form submission, the date of hidden field was updated form javascript with "dd/mm/yyyy" dateformat. When the form posts to server, the model gets error due to wrong datetime format because the server format is mm/dd/yyyy.
I would like to know what is the best way to make same date format between server and client until server culture is changed.
Thanks all
I am novice to the asp.net mvc3. It's really confusing and difficult to modify single code due to convention used in asp.net mvc3. I was trying to display only Date for BirthDate in the format 5 Sep 1999 instead which shows Date and Time.It's fine in Edit.cshtml, datepicker is used to pick the date and value is saved in database of only date. But, I have BirthDate column of Data type of Date not the DateTime and when using #Html.DisplayFor(model => model.BirthDate); in Details.cshtml shows both date and time. While Searching in google I have found and implement following code for displaying date in desire format:
#Model.BirthDate.ToString("dd MMM YYYY");
and
#Html.DisplayFor(model => model.BirthDate.ToString("dd MMM YYYY"));
It gives error no overload method takes 1 argument. Further I could use like:
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
pubilc DateTime BirthDate { get; set }
Since, I have used model first approach for Entity Framework. Where Should I implement above DisplayFormat property or what may be razor syntax to display date in right way in Details.csthml in my scenario
ok, I know I'm replying to a question posted 8 month before but my only intention is, this might be useful to others refering this question in future.
I'm also novoice to MVC and I also faced a similar problem where I need to display only the date and not the time and following worked for me.
Instead of #Html.DisplayFor(). Use <span>
So, for the case mentioned in question it would be like this:
<span>#String.Format("{0:D}", model.BirthDate)</span>
Output: Sunday, September 05, 1999
No, need to add extra class/file for formating.
The third approach is the best way according to me cos
your presentation model is dealing with all the aspects of UI and your view doesnt have unnecessary and redundant formatting code especially if you reuse the property.
enables unit testing
Consistent across different pages if you reuse the model.
You could also write an helper method that formats the date and use this consistently across all your presentation/view models.
public string FormattedDate(this DateTime dateTime)
{
return dateTime.ToString("dd MMM YYYY");
}
I like using a kind of decorator pattern to handle this kind of thing. Let's say your model class is called MyModel. Then define a wrapper class like this:
public class MyModelDecorator
{
public MyModel BaseItem { get; set; }
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
public DateTime BirthDate { get; set; }
public MyModelDecorator(MyModel baseItem)
{
BaseItem = baseItem;
}
}
Then in your Views, you can refer to either the base model properties, or to the decorated properties.
#Html.DisplayFor(m => m.BirthDate)
#Html.DisplayFor(m => m.BaseItem.SomeOtherProperty)
If there's a better solution than this one, then I'd really like to hear it....
For any ASPX user sumbad answer helped but this is how you do it:
<%=Html.Enconde(String.Format("{0:D}", item.yourDate))%>
Hope this helps someone.
I have a page with many date fields, which can be dynamically added on client side. I have a DatTime? property on editor template for this field:
[Display(Name = "Bar Admission Date")]
public DateTime? AdmissionDate { get; set; }
When I'm submitting a form I get a null data in AdmissionDate field because binder doesn't know the format of the field.
I have 2 ideas of how t oovercome this issue:
Make a string field in model and parse it on a server side. Simple and pretty quick.
Write a custom model binder for date fields. I don't like this solution because I don't know the keys for all fields that I will use.
Is there better solution? I searched how can I overload TextboxFor method in order to pass it a culture, but I didn't find
Sounds like you should use an enumerable (IList/ICollection) of DateTime?. Phil Haacked has a good article on model binding to a list (even when the number of items is dynamic).
Updated
As for the formatting problem, I would look at how to set the culture for the project/model binder.
My application is setted with pt-BR culture (Date is dd-mm-yyyy) in web.config:
<globalization enableClientBasedCulture="false" requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="iso-8859-15" responseHeaderEncoding="utf-8" resourceProviderFactoryType="string" enableBestFitResponseEncoding="true" culture="pt-BR" uiCulture="pt-BR" />
All DateTime created on my system is in right format, but I created a controller method like that:
public ActionResult Test(DateTime date)
{
}
Calling that method direct in the browser is passing null when the date is with portuguese-br format, like that:
mysite/Test/?date=19/01/2012 => date = null in my controller
mysite/Test/?date=01/01/2012 => date is fine, but in US format (mm-dd-yyyy)
How can I fix that, to accept my date format?
There's a gotcha with the default model binder that is not easy to know about but once you know it you no longer make the same mistake:
When you use a POST request, the default model binder uses your culture settings to parse the dates.
When you use a GET request, the default model binder uses CultureInfo.InvariantCulture to parse the dates and ignores your current culture settings.
Since you are using a GET request and passing the date as a query string parameter, you should format it using the invariant culture format when sending it in the url. The correct way to format your date as a query string parameter is yyyy-MM-dd.
You may take a look at the following blog post which gets into more details.
As someone who does a lot of work with US companies, I've had a lot of experience with date issues.
My best advice is to choose an unambiguous format when transmitting.
dd-MMM-yyyy
and
yyyy-MM-dd
Are safe bets, and will be successfully parsed by DateTime.Parse(obj).
If changing the date format is not an option, you should look at DateTime.ParseExact, which allows you to specify the exact format string you are after.
One approach would be to accept the date as a string and then manipulate it in the controller to the correct locale/culture.
Got the same problem using an #Html.Action(..) in a view. For this situation it can be solved by putting the DateTime in a model:
public class MyModel
{
public DateTime Value {get;set;}
}
and in the view:
#Html.Action("MyAction", new { myModel })
Note the new { } around the instance of MyModel, this way the DateTime is not converted to a string. This solution only works for Html.Action() and not for Html.ActionLink() or Url.Action() since MVC is doing a myModel.ToString() in the URL.
In my model I have the following property:
[DataType(DataType.Currency)]
public decimal? Budget { get; set; }
When the user enters in $1,200.34, I need that value to be valid and strip out the currency symbol and comma.
In my controller I'm doing:
if (race.Budget != null)
{
race.Budget.ToString().Replace("$", "").Replace(",", "");
}
The problem is that client validation doesn't pass the value for budget into the controller. I get a value of null. How can I override the client validation so that I can strip out the currency symbol and comma?
Thank you in advance for the help.
UPDATE
So here's the strange thing. Let's say I want to bypass client validation all together. I added #{ Html.EnableClientValidation(false); } to my view and it's still sending a null value for Budget when I submit to the controller.
This isn't a client side validation problem. Your model has a field of type decimal? The model binder will try to bind a value of $123,456.78 into that and fail, so the value will be null. Here's one way to get around this:
Change your model to have a string property that masks your decimal:
public decimal? Budget { get; set; }
public string BudgetText {
get {
return Budget.HasValue ? Budget.ToString("$") : string.Empty;
}
set {
// parse "value" and try to put it into Budget
}
}
Then, just bind to BudgetText from your View. Validate it as a string with a regular expression that accepts only money input. It'll probably be the same regex you can use for your BudgetText's set method
So you can probably hook in some JQuery to pre-process the form field to strip the characters off you don't want (prior to form submission to the server). This is probably the quickest, dirtiest approach.
For something reusable, have a look into custom client validation adapters. The links aren't spot on, but should get you in the right direction. For Brad's screencast, I believe the relevant parts are fairly early on.
Check out the support for jQuery localization
cliente validation using jQuery validate for currency fields
also there is a plugin for currency validation as well
http://code.google.com/p/jquery-formatcurrency/
check out this recent post as well for a $ in binding
.NET MVC 3 Custom Decimal? Model Binder