I'm generating Kendo's Datepicker in my MVC application.
#(Html.Kendo().DatePicker()
.Name("FileDate")
.Value(Session["FileDate"] == null ? DateTime.Now : Convert.ToDateTime(Session["FileDate"].ToString()))
.Events(e => e
.Change("datepicker_change")
)
)
When generated, I have an input field:
How can I update my code to add required attribute to an input field?
If there is a Model defined in the View, then you can decorate FileDate model field with [Required] DataAnnotation. Thus the extension will extract the data validation attributes automatically.
The second option is to add the required HTML attribute using the HtmlAttributes (or the InputHtmlAttributes I'm not sure what was the correct name). This will add the defined attributes to the corresponding HTML element.
Related
I've got 3 custom DropDowns for DateTime model properties, each representing Day/Month/Year that set a hidden input with each value, with an also custom model binder that works fine.
I also have created a RequiredIf validation attribute with client side validation and it works fine both server and client side adding the corresponding data-val-requiredif attributes to the hidden inputs where the selected DropDown value is stored.
The problem comes when I use this RequiredIf attribute on DateTime property using the custom control.
[RequiredIf(...)]
public DateTime Start { get; set; }
and the issue is in each dropdown hidden input generated with Html.HiddenFor (binded to Start.Month in this example):
<input data-val="true" data-val-number="The field Month must be a number." id="Start_Month" name="Start.Month" type="hidden" value="">
The problem is pretty clear, the validation attribute is on the DateTime property, not it's Month subproperty, so the data-val-requiredif... validation attributes are not set on that input.
Question:
What is the best approach to make Day/Month/Year inherit the dataannotation validation attributes from it's DateTime model?
I wouldn't use data attribute names with multiple hyphens like your "data-val-number". I've also had issues with upper case so always use one hyphen after data and always lower case.
If you're passing the date back to a controller in separate pieces (i.e. month / day / year), you'll have to put it back together in a DateTime format on the server for the validation to work.
If you're putting the date together in a JSON model to pass back to the controller, MVC will convert the JSON to a model object for you. Make sure your JSON model is exactly the same as what the controller parameter is expecting.
I have a template editor, Currency.cshtml like this:
#model decimal?
...
string value =
// Some calculations that returns value formatted as currency
Currency: #value<br/>
#Html.TextBox("", value, attributes)
I have a view which uses this template like this:
#Html.EditorFor(m => m.Amount.Value, "Currency", someAdditionalViewData)
When this view is rendered as a partial directly inside another view, the result is as expected: both the text, and the editor show the formatted variable "value", like so:
Currency: 1.223,18 <== well formatted
[ 1.223,18] <== this is the input type=text, well formatted
However, if I get the view using Ajax (Ajax.ActionLink), I get the firs part formatted, but the second one unformatted, like so:
Currency: 1.223,18 <== well formatted
[ 1223.18] <== this is the input type=text, not formatted!!
Any idea why this can be going on? Should I change the final #Html.TextBox("", value, attributes) in my template for something else?
I don't know the reason, but after investigating for some time, I can assure that the final call to #Html.TextBox("", value, attributes), on an Ajax request behaves in a different way than on a PartialView render.
In a PartialView render, it creates the desired input element, with the provided formatted value. However, in an ajax request, it looks up for info on the model and creates its own version of the textbox, including the unobstrusive validation attributes and so on.
The only way to solve this problem is not to use the TextBox method, but create an input writing it directly with a TagBuilder. Pay attention to the way of getting the Id and name for the input element.
#{
string value = ... // Format as desired
// Create the required attributes
// NOTE: HtmlAttributes is simply a custom "fluent" attribute builder,
// inherited from IDictionay<string,object>
var attributes = HtmlAttributes.Empty
.Add("type", "text")
.Add("value", value) // formatted value
.Add("id", ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(""))
.Add("name", ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(""))
.AddStyle("text-align", "right");
// You can add extra attributes, i.e. unobtrusive validation, provided by user...
var extraAttibutes = ...
attributes.Merge(extraAttributes);
// Use the tag builder to create the input
TagBuilder tb = new TagBuilder("input");
foreach (var attribute in attributes)
{
tb.Attributes.Add(attribute.Key, attribute.Value.ToString());
}
var textBox = tb.ToString(TagRenderMode.SelfClosing);
// Then, either write it directly to the writer...
ViewContext.Writer.Write(textBox);
}
#* ...or use Html.Raw *#
#Html.Raw(textBox)
Of course, there are a lot of details omitted (how to get unobtrusive or any other extra attributes for the tag and so on). The best soultion would be to discover why the behavior changes from a "complete" render and an ajax request render. All the View metadata looks exactly the same, but works in a different way.
I also had a partialview that used an editortemplate which worked when initially loading the page. However when using ajax to call for the partial the editortemplate wasn't used.
For me turned out I had to move it to a different folder:
From
Views/[Controllername]/EditorTemplates
To
Views/Shared/EditorTemplates
Nearly all my properties in my view model are decorated with [Editable(false)]', but when I scaffold a view, that usesEditorFor` these properties, they are all still editable on the form.
Must I now manually change all EditorFor to DisplayFor to prevet editing? OK, I will eventually change the T4 that generates the edit form, but really, what purpose does this attribute serve then?
EditorFor works with metadata, so if you want to add html attributes you could always do it. Another option is to simply write a custom template and use TextBoxFor:
<%= Html.TextBoxFor(model => model.Control.PeriodType,
new { disabled = "disabled", #readonly = "readonly" }) %>
Extracted from here:
Html attributes for EditorFor() in ASP.NET MVC
I have a model with a DateTime property that in one place is placed in a hidden input field.
#Html.HiddenFor(m => m.StartDate)
Which generates the following HTML:
<input id="StartDate" name="StartDate" type="hidden" value="1/1/2011 12:00:00 AM" >
The problem is that the time is included in the value and my custom date validation expects a date in the format of ##/##/#### thus causing validation to fail. I can easily alter my custom date validation to make this situation work but I would rather make it so that the hidden field puts the value in the correct format.
I have tried using the DisplayFormat attribute on the model property but that doesn't seem to change the format of the hidden input.
I do realize that I could just create the hidden input manually and call StartDate.ToString("MM/dd/yyyy") for the value but I am also using this model in a dynamically generated list of items so the inputs are indexed and have ids like Collection[Some-Guid].StartDate which would make it a bit more difficult to figure out the id and name of the input.
Is there anyway to make the 'value' value come out in a specific format when rendering the field on the page as a hidden input?
You could use a custom editor template:
public class MyViewModel
{
[UIHint("MyHiddenDate")]
public DateTime Date { get; set; }
}
and then define ~/Views/Shared/EditorTemplates/MyHiddenDate.cshtml:
#model DateTime
#Html.Hidden("", Model.ToString("dd/MM/yyyy"))
and finally in your view use the EditorFor helper:
#model MyViewModel
#Html.EditorFor(x => x.Date)
This will render the custom editor template for the Date property of the view model and consequently render the hidden field with a value using the desired format.
I'm using ASP.NET MVC 3 + FLUENT VALIDATION + NINJECT
I have model X and rules for that model are something like this:
RuleFor(c => c.FirstName).NotEmpty();
RuleFor(c => c.LastName).NotEmpty();
I spotted a little strange thing, the engine puts validation attributes on all hidden elements and on dropdowns, radio buttons, etc.., and I didn't specified this in the validation configuration for that model, so I guess it is by default...
<input type="hidden" value="1" name="Id" id="Id" data-val-required="'Id' must not be empty." data-val-number="The field Id must be a number." data-val="true">
Validation works because hidden element always have a value, but I have a problem with radio buttons. For example, if I don't want one radio button always to be selected by default but empty and if I want to put validation rules on that item, the rendering puts default validation attributes and on top of my rules, so it's getting messed up and validation doesn't work properly...
Anyone had similar issues or knows about this, or do I have to pull the ASP.NET MVC source and look it up by myself? :)
Semi-Lazy and little-pushed-down-by-deadlines coder
Edit:
I tried proposed solution from this link:
Fluent Validations. Error: Validation type names in unobtrusive client validation rules must be unique
but asp.net mvc emits required attributes on each field regardless of AddImplicitRequiredAttribute settings...
Make the Id property on your view model a nullable integer.
So instead of:
public int Id { get; set; }
you should use:
public int? Id { get; set; }
Same stands true for any other value types that you don't want to be required. You should use nullable types.
Html helpers automatically emit data-val attributes for all non-nullable types which is by design and if you do not want this behavior you will have to write your own custom HTML helpers to generate your input fields and dropdowns. You can no longer rely on TextBoxFor and DropDownListFor helpers as that's how they are designed.