Monday, February 22, 2010

Fun with Lambdas & HtmlHelpers




Since I started using fluentHtml, I’ve loved this syntax: this.Textbox(f=>f.Whatever).Styles(display=>”none”)

The fact that it’s SO easy to read is what I love…specifically the Styles() portion. So I downloaded the MvcContrib source to see how they were handling it and it was actually pretty simple. Basically, you setup a param like this:

params Func<string, string>[] values

So let’s do a quick sample for a…submit button. I want to be able to type this below for a basic submit button with the text “Sample Submit”:

<%=Html.SubmitButton("Sample Submit") %>

If I want to add an accesskey attribute, I want to just type this:

<%=Html.SubmitButton("Sample Submit", accesskey=>"S") %>

If I want to add an id to the button, I want to do this:

<%=Html.SubmitButton("Sample Submit", accesskey=>"S", id=>"sampleid") %>

If I want to add a css class, I want to just do this:

<%=Html.SubmitButton("Sample Submit", accesskey=>"S", id=>"sampleid", cssclass=>"sampleclass") %>

Okay, so I think you get the idea. By the way, the reason we can’t put class=>”sampleclass” is because class is a reserved word and throws an error. I’ll show you how I get around the issue.

So what does this extension method look like? Here it is:

public static string SubmitButton(this HtmlHelper htmlHelper, string textValue, params Func<string, string>[] values)
{
var attributes = new StringBuilder();
foreach (var func in values)
attributes.AppendFormat(
"{0}=\"{1}\" "
, func.Method.GetParameters()[0].Name.ToLower().Replace("cssclass", "class"), func(null));

return string.Format("<input type=\"submit\" value=\"{0}\" {1}/>", textValue, attributes);
}

So let’s break this down.


  1. Notice the params keyword in the method signature. What this allows you to do is pass zero or many Func<string,string>s into the method. Note: when using the params keyword, it should be the last argument in the signature and it should be a defined as an array.

  2. If you’re new to StringBuilder, it is generally used when concatenating string together because it performs better than plain ole string.

  3. So I’m appending the format of attributename=”value”, which is represented by the “{0}=\”{1}\” “. (Notice the AppendFormat signature contains a params object[])

  4. The first argument represented by {0} is the name of the parameter of the generic Func<>. So I’m getting the first parameter from the Func<> method and lowering the name and replacing cssclass with class.

  5. The second argument represented by {1} is the value of the lambda, which we get by calling func(null). We don’t have to pass in null, we could pass in anything we want to func because we’re not using it for anything, we’re just returning the value we set after the =>. However, null is the cleanest method :)

  6. Lastly, I return the formatted submit html code, which sets the value and attributes. If there aren’t any, then the {1} is empty and basically ignored.

Well, that’s it. I thought I’d share because I think it’s something that’s pretty useful, cool, and easy to read for the end-user of your code. Thanks for reading!


Shout it

kick it on DotNetKicks.com

blog comments powered by Disqus
Related Posts Plugin for WordPress, Blogger...