Consistent rendering of fields in Custom Forms

Oct 17, 2012 at 9:22 AM
Edited Oct 17, 2012 at 9:26 AM

The rendering of fields in Orchard Custom Form seems to follow a pattern of label and input tags within a fieldset tag. Like so in the Input Field view found at Modules/Orchard.Fields/Views/EditorTemplates/Fields/Input.Edit.cshtml...

@model Orchard.Fields.Fields.InputField
@using Orchard.Utility.Extensions;
@using Orchard.Fields.Settings;
@{
    var settings = Model.PartFieldDefinition.Settings.GetModel<InputFieldSettings>();
}
<fieldset>
    <label for="@Html.FieldIdFor(m => m.Value)" @if(settings.Required) { <text>class="required"</text> }>@Model.DisplayName</label>
    <input type="@settings.Type.ToString().ToLower()" id="@Html.FieldIdFor(m => m.Value)" name="@Html.FieldNameFor(m => m.Value)"@if(!String.IsNullOrWhiteSpace(settings.Title)) {<text> title="@settings.Title"</text>} value="@Model.Value"@if(settings.Required) {<text> required="required"</text> }@if(settings.AutoFocus) {<text> autofocus="autofocus"</text> }@if(settings.AutoComplete) {<text> autocomplete="on"</text> }@if(!string.IsNullOrWhiteSpace(settings.Placeholder)) {<text> placeholder="@settings.Placeholder"</text>}@if(!string.IsNullOrEmpty(settings.Pattern)) {<text> pattern="@settings.Pattern"</text>}@if(!string.IsNullOrEmpty(settings.EditorCssClass)) {<text> class="@settings.EditorCssClass"</text>} else {<text> class="textMedium"</text>} @if(settings.MaxLength > 1) {<text> maxlength="@settings.MaxLength.ToString()"</text>} />
    @Html.ValidationMessageFor(m => m.Value)
    <span class="hint">@settings.Hint</span>
</fieldset>

This renders as something like this:

<fieldset>
    <label for="MyFormName_MyFieldName_Value" class="required">First Name</label>
    <input type="text" id="MyFormName_MyFieldName_Value" name="MyFormName.MyFieldName.Value" value="" required="required" autofocus="autofocus" autocomplete="on" placeholder="Your first name" class="textMedium">
    
    <span class="hint"></span>
</fieldset>

The Choice List Custom Field view at Modules/Contrib.ChoiceList/Views/EditorTemplates/Fields/Contrib.ChoiceList.cshtml is a bit different:

@model Contrib.ChoiceList.ViewModels.ChoiceListFieldViewModel
@using Orchard.Utility.Extensions;

<fieldset>
	<legend>@Model.Name</legend>

	@if( Model.ListMode == "radio" )
	{
		foreach (var option in Model.Options.Split(';'))
		{
			if( string.IsNullOrWhiteSpace(option) )
			{
				<label>@Html.RadioButton("SelectedValue", "", string.IsNullOrWhiteSpace(Model.SelectedValue))<i>unset</i></label>
			
			}
			else
			{
				<label>@Html.RadioButton("SelectedValue", option, (option == Model.SelectedValue))@option</label>
			}
		}
	}
	else
	{
		@Html.DropDownListFor(m=>m.SelectedValue, new SelectList(Model.Options.Split(';'), Model.SelectedValue))
		@Html.ValidationMessageFor(m=>m.SelectedValue)
	}
</fieldset>

Where the standard fields use the label tag for the name of the field, both radio buttons and drop down lists employ legend tags. This makes sense for a group of radio buttons, but not for drop down lists - in the browser, it appears that the humble drop down list is a major section of the form.

To keep the consistency with other fields, how about making rendering of the legend tag conditional on the custom field being a radio button, and using a label for the drop down list? A view like the following would work...

@model Contrib.ChoiceList.ViewModels.ChoiceListFieldViewModel
@using Orchard.Utility.Extensions;

<fieldset>

	@if( Model.ListMode == "radio" )
	{
	<legend>@Model.Name</legend> 	//put the legend tag here instead.
		foreach (var option in Model.Options.Split(';'))
		{
			if( string.IsNullOrWhiteSpace(option) )
			{
				<label>@Html.RadioButton("SelectedValue", "", string.IsNullOrWhiteSpace(Model.SelectedValue))<i>unset</i></label>
			
			}
			else
			{
				<label>@Html.RadioButton("SelectedValue", option, (option == Model.SelectedValue))@option</label>
			}
		}
	}
	else
	{
		@Html.LabelFor(m=>m.SelectedValue)	//non-radio buttons need a label
        	@Html.DropDownListFor(m=>m.SelectedValue, new SelectList(Model.Options.Split(';'), Model.SelectedValue))
		@Html.ValidationMessageFor(m=>m.SelectedValue)
	}
</fieldset>

What do you think? Thanks for having a look!