Skip to content

Instantly share code, notes, and snippets.

@leojh
Created May 23, 2012 15:43
Show Gist options
  • Save leojh/2776025 to your computer and use it in GitHub Desktop.
Save leojh/2776025 to your computer and use it in GitHub Desktop.
FubuMVC Sample HtmlConventions
using System;
namespace Is3.App.Web.IS3Portal.Core2.Web.Conventions.Html.Attributes
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class DisplayNameAttribute : Attribute
{
public DisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; private set; }
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class HiddenAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public class OptionAttribute : Attribute
{
private readonly string _text;
public OptionAttribute(string text)
{
_text = text;
}
public string Text
{
get { return _text; }
}
}
}
//In your FubuRegistry, add the following command:
HtmlConvention<PortalHtmlConvention>();
using System.Linq;
using System.Reflection;
using FubuMVC.Core.UI;
using FubuMVC.Core.UI.Configuration;
using FubuValidation;
using HtmlTags;
using Is3.App.Web.IS3Portal.Core2.Web.Conventions.Html.Attributes;
using Is3.App.Web.IS3Portal.Core2.Web.Validation;
using Is3.Common.Utils;
namespace Is3.App.Web.IS3Portal.Core2.Web.Conventions.Html
{
public class PortalHtmlConvention : HtmlConventionRegistry
{
public PortalHtmlConvention()
{
ApplyInputsConventions();
ApplyLabelsConventions();
}
private void ApplyInputsConventions()
{
//Apply maxlength attr to Model Fields decorated with MaximumStringLengthAttribute
Editors.ModifyForAttribute<MaximumStringLengthAttribute>((tag, attr) => tag.Attr("maxlength", attr.Length));
//Apply maxlength attr to Model Fields decorated with EmailAttribute
Editors.ModifyForAttribute<EmailAttribute>(
(tag, attr) => tag.Attr("maxlength", EmailAttribute.EmailMaximumLength));
//Apply id attribute to inputs
Editors.Always.Modify(AddElementId);
//Make Model Fields decorated with HiddenAttribute hidden inputs
Editors.ModifyForAttribute<HiddenAttribute>((tag, attr) => tag.Attr("type", "hidden"));
//Make input type of password for Model Fields decorated with PasswordAttribute
Editors
.ModifyForAttribute<PasswordAttribute>((tag, attr) =>
{
tag.Attr("type", "password");
tag.Attr("maxlength",
PasswordAttribute.PasswordMaximumLength);
});
//Builds drop downs from nullable Enum properties where the Enum is Decorated with the OptionAttribute to render the text of Option tags
Editors
.If(e => e.Accessor.PropertyType.IsEnumOrNullableEnum())
.BuildBy(BuildSelectInputsFromEnumerations);
}
private void ApplyLabelsConventions()
{
//Override Label Text convention when DisplayName attribute is present
Labels.ModifyForAttribute<DisplayNameAttribute>((tag, attr) => tag.Text(attr.DisplayName));
//Append * to Model Fields decorated with RequiredAttribute
Labels.ModifyForAttribute<RequiredAttribute>((tag, attr) => tag.Append(new HtmlTag("span").Text("*")));
//Apply for atttribute to labels
Labels.Always.Modify(((r, tag) =>
{
tag.Attr("for", r.Accessor.Name);
tag.Text(tag.Text() + ":");
}));
}
private HtmlTag BuildSelectInputsFromEnumerations(ElementRequest request)
{
var enumType = request.Accessor.PropertyType.IsEnum
? request.Accessor.PropertyType
: request.Accessor.PropertyType.GetGenericArguments().Single();
var currentModelPropertyValue = request.StringValue();
var selectTag = new SelectTag();
var defaultMessage = string.Format("Select {0}", enumType.Name);
selectTag.Children.Add(new LiteralTag(string.Format(@"<option value="""">{0}</option>", defaultMessage)));
foreach (var optionEnumField in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
{
var optionAttribute = optionEnumField.GetCustomAttributes(typeof(OptionAttribute), false).Cast<OptionAttribute>().SingleOrDefault();
if (optionAttribute != null)
{
var optionTag = selectTag.Option(optionAttribute.Text, optionEnumField.Name);
if (currentModelPropertyValue.Equals(optionEnumField.Name))
optionTag.Attr("selected", "selected");
}
}
return selectTag;
}
private void AddElementId(ElementRequest request, HtmlTag tag)
{
if (!tag.IsInputElement() || tag.HasAttr("id"))
return;
tag.Attr("id", request.ElementId);
}
}
}
//To Use The Option Attribute on an enum
public enum Prefix
{
[Option("Mr.")]
Mr = 1,
[Option("Mrs.")]
Mrs,
[Option("Ms.")]
Ms,
[Option("Dr.")]
Dr
}
//Using Enums in your Models
public class MyModel
{
public string FirstName {get; set;}
public int Age {get;set;}
//It's important to declare all enums in the model as nullable
public Prefix? {get;set;}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment