MVC 5 view still render required field - asp.net-mvc

Initially I have two required date time properties in my model. The client side validation works fine for them. But when i comment out the required DataAnnotation on one of the property, MVC view still generating data-val=true, ect... How to i fix this so that mvc view is rendering field is not required.
I've try $('#endDate').rules('remove', 'required')
but it still checking required field.
Model:
public class mymodel{
...
[Required]
public Datetime startDate { get; set;}
//[Required]
public Datetime endDate {get; set}
}
View:
#Html.LabelFor(model => mode.endDate ....)
#Html.EditorFor(model => model.endDate, new { htmlAttributes = new { #class = "form-control", id="endDate" } })
View Render
<input class="form-control text-box single-line hasDatepicker input-validation-error" data-val="true" data-val-date="The field endDate must be a date." data-val-required="The endDate field is required." id="endDate" ....>
<span class="text-danger field-validation-error" ....>
<span for="endDate" class> The endDate field is required.</span>
</span>

Properties with non-nullable types (such as DateTime) are inherently required, with or without the Required attribute, because they must have some value. To make it optional, you must use a nullable DateTime:
public DateTime? endDate { get; set; }

Related

Model DataAnnotation [DataType(DateType.Date)] renders DatePicker but hides my value?

I have 3 date fields in my INV_Assets model: acquired_date, disposed_date, and created_date. I have them displaying as format MM/dd/yyyy in some #Html.EditorFor()'s.
What I'm attempting to do now is add a simple datepicker functionality, which is where I came across THIS post about using [DataType(DataType.Date)] attribute on my model properties. My created_date is currently set as:
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime created_date { get; set; }
This renders the dropdown functionality, but the value in the box appears exactly as "mm/dd/yyyy" instead of showing the actual value. For example, if I remove the [DataType(DataType.Date)] attribute:
[Required]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime created_date { get; set; }
My value shows up as "02/10/2015" without the datepicker functionality.
Can anyone provide an example of how I can render this datepicker functionality but show the actual value of my field in the box (when a value is present)?
EDIT:
The created_date field on my View is currently defined as follows (following Chris' suggestion I attempted to force the value to be in format YYYY-MM-DD):
<div class="form-group">
#*#Html.LabelFor(model => model.created_date, htmlAttributes: new { #class = "control-label col-md-2" })*#
<span class="control-label col-md-2">Created Date:</span>
<div class="col-md-10">
#Html.EditorFor(model => model.created_date, new { htmlAttributes = new { #class = "form-control", #Value = Model.created_date.ToString("YYYY-MM-DD") } })
#Html.ValidationMessageFor(model => model.created_date, "", new { #class = "text-danger" })
</div>
</div>
This renders the following code:
<input value="YYYY-02-DD" class="form-control text-box single-line" data-val="true" data-val-date="The field created_date must be a date." data-val-required="The created_date field is required." id="created_date" name="created_date" type="date">
This worked for me
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
Following Chris Pratt's Idea
I'm assuming you're also using the HTML 5 date input type, i.e. <input type="date">. The value for a date input type, must be an ISO formatted date: YYYY-MM-DD. The placeholder you see there is just the browser providing a more user-friendly display, but it's converting to/from the ISO format behind the scenes. If you don't provide a proper ISO date, then it's essentially treated by the browser as no value at all.

mvc data annotation validator for datetime always shows required

when I submit my form, Termination date field shows "Termination Date field is required" even though I haven't defined it as required anywhere.
my model is defined as:
[Display(Name = "Termination Date")]
public DateTime TerminationDate { get; set; }
razor code is:
<div class="col-md-6 form-group">
#Html.LabelFor(model => model.Posting.TerminationDate)
#Html.TextBoxFor(model => model.Posting.TerminationDate, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Posting.TerminationDate)
</div>
I do not want any type of validation on this field. How can I do that?
Make the property nullable
DateTime? or Nullable<DateTime>
Or reconfigure the convention
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

MVC3 EditorFor losing value on postback

I've created and date editorfor template but the value is getting lost on postback. Please can anyone help?
Here's my Date.cshtml stored in the 'shared/editortemplates' folder:
#model DateTime
<div class="input-append">
<input type="text" class="input-small datePicker" id="#ViewBag.Id" name="#ViewBag.Id" />
<span class="add-on"><i class="icon-th"></i></span>
</div>
Here's the view:
#Html.EditorFor(m => m.RequiredByDate, new { Id = "RequiredByDate" })
And the property on the viewmodel:
[Display(Name = "Required by date")]
[Required(ErrorMessage = "Required by date is required.")]
[DataType(DataType.Date)]
public DateTime RequiredByDate { get; set; }
Any help greatly appreciated.
I've not set the value on the input. what an idiot.
<input type="text" class="input-small datePicker" id="#ViewBag.Id" name="#ViewBag.Id" value="#Model.ToString("dd/MM/yyyy")" />

bool property without Required attribute is required

have a simple ViewModel with three properties like so:
public bool RememberMe { get; set; }
In my view I have a simple #Html.CheckBoxFor(p => p.RememberMe)
I am using Client Side validation enabled using Html.EnableClientValidation();
Why is this being set as a required field?
Try a nullable bool.
public bool? RememberMe { get; set; }
With reference types there are a number of default validation rules applied. If a reference type is not nullable, it becomes required by default. The best illustration of this is if you use a textbox to display some properties (not something you would do in your site, but good for testing purposes):
Model:
public bool? MyBool { get; set; }
public int MyInt { get; set; }
View:
#Html.TextBoxFor(p => p.MyBool)
#Html.TextBoxFor(p => p.MyInt)
You can see from a view source what happens on the page:
<input id="MyNullBool" name="MyNullBool" type="text" value="">
<input data-val="true" data-val-required="The MyBool field is required." id="MyBool" name="MyBool" type="text" value="False">
<input data-val="true" data-val-number="The field MyInt must be a number." data-val-required="The MyInt field is required." id="MyInt" name="MyInt" type="text" value="0">
The nullable bool has no validation attributes, whereas the bool has a data-val-required tag. The int has a data-val-required tag and a data-val-number attribute
Of course, on a checkbox this is all pretty redundant as it can only be checked (true) or not checked (false) so a required tag isn't much use.
#Html.CheckBoxFor(c => c.TermsAndConditions, new { required = "required" })
#Html.ValidationMessageFor(c => c.TermsAndConditions, "you must agree to terms and conditions of Service.)"

Knockout.js bind array of objects to repeated <select>'s

I've got this Knockout.js view model:
{
"LanguageFromTos":
[{
"LanguageFromToId":0,
"LanguageFromId":2,
"LanguageFrom":null,
"AllLanguagesFrom":[
{"Selected":false,"Text":"English","Value":"1"},
{"Selected":false,"Text":"French","Value":"2"},
{"Selected":false,"Text":"Spanish","Value":"3"}
],
"LanguageToId":1,
"LanguageTo":null,
"AllLanguagesTo":[
{"Selected":false,"Text":"English","Value":"1"},
{"Selected":false,"Text":"French","Value":"2"},
{"Selected":false,"Text":"Spanish","Value":"3"}
],
"Users":null
}]
}
And these html <select>s:
<div class="LanguageFromToRow">
<input type="hidden" name="languageFromTos.index" autocomplete="off" value="c50532b0-65d2-4a81-baeb-59b768fd120f" />
<label for="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageFromId">From</label>:
<select data-bind="???" data-val="true" data-val-number="The field From must be a number." data-val-required="The From field is required." id="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageFromId" name="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageFromId">
<option value="1">English</option>
<option selected="selected" value="2">French</option>
<option value="3">Spanish</option>
</select>
<span class="field-validation-valid" data-valmsg-for="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageFromId" data-valmsg-replace="true"></span>
<label for="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageToId">To</label>:
<select data-bind="???" data-val="true" data-val-number="The field To must be a number." data-val-required="The To field is required." id="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageToId" name="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageToId">
<option selected="selected" value="1">English</option>
<option value="2">French</option>
<option value="3">Spanish</option>
</select>
<span class="field-validation-valid" data-valmsg-for="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageToId" data-valmsg-replace="true"></span>
delete
</div>
Can anyone tell me what I need to add to the data-bind attributes of each select to tie them up to the Knockout.js view model? The value of the first select should be bound to LanguageFromId in the view model and the value of the second select should be bound to LanguageToId in the view model.
LanguageFromTos in the view model is an array, so all of what you see inside may be repeated (2 LanguageFromTos would result in the LanguageFromToRow div being repeated twice, for example). The number of repeats is set both server-side (data posted by the controller may have multiple LanguageFromTos) and client-side (an 'add' button that allows the user to add another div with its contained selects) in different cases, so I presume Knockout's templating is a no-go as MVC needs to loop through and render each row so that it can catch them all on a 'normal' post back.
Any help much appreciated!
Edit
Here's the MVC model for the page:
public class DirectorySearchModel
{
[Display(Name = "User name contains")]
public string UserName { get; set; }
[Display(Name = "First name contains")]
public string FirstName { get; set; }
[Display(Name = "Last name contains")]
public string LastName { get; set; }
[Display(Name = "Languages translated")]
public IEnumerable<LanguageFromTo> LanguageFromTos { get; set; }
}
Here's the LanguageFromTo object:
public class LanguageFromTo
{
[Key]
public virtual int LanguageFromToId { get; set; }
[Display(Name = "From")]
public virtual int LanguageFromId { get; set; }
[ForeignKey("LanguageFromId")]
public virtual Language LanguageFrom { get; set; }
public virtual IEnumerable<SelectListItem> AllLanguagesFrom { get; set; }
[Display(Name = "To")]
public virtual int LanguageToId { get; set; }
[ForeignKey("LanguageToId")]
public virtual Language LanguageTo { get; set; }
public virtual IEnumerable<SelectListItem> AllLanguagesTo { get; set; }
public virtual ICollection<User> Users { get; set; }
}
And here's the cshtml code for the MVC view. This code sits in a partial that's repeated depending on how many LanguageFromTos there are in DirectorySearchModel that's passed to the MVC view:
<div class="LanguageFromToRow">
#using(Html.BeginCollectionItem("languageFromTos")) {
#: #Html.LabelFor(m => m.LanguageFromId): #Html.DropDownListFor(m => m.LanguageFromId, Model.AllLanguagesFrom, new { data_bind = "value: getLanguageFromToById(0).LanguageFromId" }) #Html.ValidationMessageFor(m => m.LanguageFromId)
#: #Html.LabelFor(m => m.LanguageToId): #Html.DropDownListFor(m => m.LanguageToId, Model.AllLanguagesTo, new { data_bind = "value: getLanguageFromToById(0).LanguageToId" }) #Html.ValidationMessageFor(m => m.LanguageToId)
delete
}
</div>
Your design here has some poor choices. Knockout's Templating is the right choice for this, but it is going to require you to start thinking in a different sort of pattern. You do not need to use partials to accomplish the repetition you are after.
Here is a fiddle demonstrating a templating solution. http://jsfiddle.net/tyrsius/XgwLD/3/
Some notes: to populate incomingData, an easy method will be to use #Html.Raw(Json.Encode(Model.DirectorySearchModel ));. This will turn your model into a JSON object, which the viewModel's constructor can easily use.
Now, I didn't use any MVC code in the fiddle because I can't, but you've obviously already found how you can put data-bind in the MVC helpers. This isn't always a bad idea, but for things like selects and DIVs that you want to use as templates, it will probably just makes things harder to read.

Resources