I am working on a WCAG AA compliant site. This means that input forms should have the following attributes if they are no null or empty:
required='required'
value='{the value}'
If they are null or empty then those attributes should not be present. Hence the following will fail WCAG on two accounts.
<input type='date' required='false' value='' />
I started off with an if statement in the razor view:
@if (Model.HasValue)
{
<input type="date" id="@Model.Name" name="@Model.Name" min="1990-01-01" max="2100-01-01" value="@Model.CoercedValue" />
}
else {
<input type="date" id="@Model.Name" name="@Model.Name" min="1990-01-01" max="2100-01-01" />
}
but this starts to get ugly real fast when other optional attributes are added. It becomes four statements when the required attribute is added.
I feel there are two ways to go on this, either push the logic to the ViewModel so it returns an attribute string:
public string this[string key]
{
get {
switch (key){
case "Required":
return IsRequired?"required='required'":String.Empty;
case "Value":
return HasValue ? String.Format("value='{0}'", CoercedValue) : String.Empty;
default:
return String.Empty;
}
}
}
The View then looks like this:
<input type='date' @Model["Required"] @Model["Value"] />
The alternate is to put this logic in a code block in the View
@{
RequiredAttr = IsRequired?"required='required'":String.Empty;
ValueAttr = HasValue ? String.Format("value='{0}'", CoercedValue) : String.Empty;
}
and the rest of the view markup:
<input type='date' @RequiredAttr @ValueAttr />
I am leaning to the markup in the ViewModel, but is that the best place for it? Am I missing a pattern that would solve this?
My personal take is that "no code in the View" is a strong guideline, but not absolute gospel. I have used code in my Views on occasions where the logic is
I think Matthew's comment that an extension to make a custom WCAG-compliant input field would work well. It's repeatable, consistent, and encapsulates the concern cleanly.