Spark Macro for Uploadify, Take One-B
aspnetmvc, programming, spark May 22nd, 2009Matt recently wrote in ASP.NET MVC HtmlHelper for Uploadify, Take One about a fairly common problem in the shades of gray where html and code concerns overlap. It’s a game of trying to get the least of both evils mixed in with the other.
Matt makes a particularly insightful remark in a comment, “what I dislike is how the balance of language in the helpers tends to shift from C# to JavaScript or HTML.”
I’d agree with that. On the one hand you’re trying to avoid excessive code in your template, but in doing so you’re dragging markup into your code. It’s actually a great example of a primary use-case for a macro in the Spark language, which lets you declare a helper method in the template language.
Here is the HtmlHelper extension exactly as it appeared on Matt’s post:
/// <summary>
/// Renders JavaScript to turn the specified file input control into an
/// Uploadify upload control.
/// </summary>
/// <param name="helper"></param>
/// <param name="name"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string Uploadify(this HtmlHelper helper, string name, UploadifyOptions options)
{
string scriptPath = helper.ResolveUrl("~/Content/jqueryPlugins/uploadify/");
StringBuilder sb = new StringBuilder();
//Include the JS file.
sb.Append(helper.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.js"));
sb.Append(helper.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.init.js"));
//Dump the script to initialze Uploadify
sb.AppendLine("<script type=\"text/javascript\">");
sb.AppendLine("$(document).ready(function() {");
sb.AppendFormat("initUploadify($('#{0}'),'{1}','{2}','{3}','{4}','{5}',{6},{7});",
name, options.UploadUrl,
scriptPath, options.FileExtensions,
options.FileDescription, options.AuthenticationToken,
options.ErrorFunction ?? "null",
options.CompleteFunction ?? "null");
sb.AppendLine();
sb.AppendLine("});");
sb.AppendLine("</script");
return sb.ToString();
}
And here’s the same helper implemented as a macro:
<macro name="Uploadify" name="string" options="UploadifyOptions">
<var scriptPath="Html.ResolveUrl('~/Content/jqueryPlugins/uploadify/')"/>
!{Html.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.js")}
!{Html.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.init.js")}
<script type="text/javascript">
$(document).ready(function() {
initUploadify($('#!{name}'), '!{options.UploadUrl}',
'!{scriptPath}', '!{options.FileExtensions}',
'!{options.FileDescription}', '!{options.AuthenticationToken}',
!{options.ErrorFunction ?? "null"},
!{options.CompleteFunction ?? "null"});
});
</script>
</macro>
The usage of the helper remains nearly identical. It’s a method on the view now instead of an Html extension method… So:
<%= Html.Uploadify("fileInput", new UploadifyOptions { ... }) %>
becomes:
<%= Uploadify("fileInput", new UploadifyOptions { ... }) %>
or rather:
!{Uploadify("fileInput", new UploadifyOptions { ... })}
May 23rd, 2009 at 3:47 pm
Спасибо за пост. Позновательно.
May 24th, 2009 at 11:30 am
That’s pretty slick. :) I have not yet had time to dig in to Spark, so this is probably an ignorant question, but can macros be embedded in a different assembly from the ASP.NET MVC app?
May 24th, 2009 at 1:53 pm
Cederash, К сожалению, я не говорю по-русски и translage.google.com не может прочитать ваш комментарий. все о цветах (All about flowers?) выглядит интересно на сайте. Есть ли новые?
Hi Matt. Not really, but that would be a great use-case to aim for in v1.1. I’d really like to see if templates could be compiled into a project as public types. Like you find with workflow, and xaml I believe.
One way to approach that in v1.0 would be to keep macros in an uploadify.spark file copied into the web app’s views/shared folder and use <import file=”uploadify”/>. It’s a bit suboptimal, but you could think of it like needing to copy jquery and it’s plugins to the web app’s content folders.
Another thing could be to have the .spark file with macros as an embedded resource in an assembly. You can configure Spark to see embedded resources in addition to files on disk, but you would still need to have an import element in the web app. And I’m pretty sure it wouldn’t show up in intellisense that way, either, so that option would probably be a lot more confusing in the end than copying an uploadify.spark file into shared.
May 25th, 2009 at 11:21 am
Very cool..but I don’t see nothing after the “becomes:”
May 25th, 2009 at 4:07 pm
Hi, Rodrigo. Really? Ah! IE and Chrome need the angle brackets inside a <code> element escaped.
Thanks for the note.
May 26th, 2009 at 8:45 am
I can dig it. Smooth. :)
May 28th, 2009 at 7:33 am
Hey is there anyway to put a macro on a file on the shared folder and call it everywhere? Whats the best way to re-use a macro?
May 28th, 2009 at 7:09 pm
Easiest place for re-use would be in ~/Views/Shared/_global.spark, but you can also put them in other files to <include file=”blah”/> if the single _global file is becoming unmanageable.
September 9th, 2009 at 2:55 pm
Основная задача Яндекса — давать ответы на вопросы пользователей!
January 12th, 2010 at 7:30 am
Хорошо написал. Так держать!!! :)