Partial files get a new powerful trick
internet, opensource, programming, spark August 10th, 2008This post is about a request for a feature from Torkel Ödegaard the other week.
Would it be possible to send the inner text to a partial?
For example lets say we have a partial named _text.spark
<text key="my_text_key"> some inner text to send to the partial view, in this case the default text for this text key. </text>
If would be nice to have the inner text be available in the partial as
a locally scoped variable (for example innerText).
The thing about that which struck me is how similar the partial files and the monorail view components would become at that point. When a monorail view component is used one of the things it can to is render the child contents which are contained on the original file. Many user controls, like panel, can do the same thing.
Let’s say you have a common rendering pattern, like rounded css corners, which you want to re-use. The simplest way to do that would be if you had a <Rounded> element you would wrap around your content.
<div>
<p>some content</p>
<Rounded>
<h3>Partial files get a new powerful trick</h3>
<p>This post is about <a href="http://groups.google.com/group/spark-dev/browse_thread/thread/b48bce693e926dc2">a request for a
feature from Torkel Ödegaard</a> the other week.</p>
</Rounded>
</div>
To make that work with a partial file you can use the new <render/> element inside the partial file.
This would be your _Rounded.spark file.
<div id="xsnazzy">
<b class="xtop">
<b class="xb1"></b>
<b class="xb2"></b>
<b class="xb3"></b>
<b class="xb4"></b>
</b>
<div class="xboxcontent">
<render/>
</div>
<b class="xbottom">
<b class="xb4"></b>
<b class="xb3"></b>
<b class="xb2"></b>
<b class="xb1"></b>
</b>
</div>
How simple is that! Another feature was also added because the specific use-case Torkel was describing needed to capture a string variable rather than write content to Output. So the other feature is the ability to use the <content> element to target a string variable.
So you could wrap the render element in a way that declares a new string innerText and captures the output into it.
<content var="innerText"><render/></content>
As always you should be able to use any additional combination of Spark features in the contents of a partial file reference. So if you’re using a partial to wrap template content you’re not limited in what you can put in that wrapped content. It can call other partials, call macros, use view components, etc. The generated code zig-zags a bit but that’s okay.
The reason I think that’s so compelling is it closes the gap between partial files and view components or user controls by another degree. Something to add next would be discrete sections which the partial could render by name.
Does anyone have a good example of a really compelling use of a user control? I’m wondering what their killer app would be to see if you could accomplish that with a partial. It’s a tricky question because a lot of them are really over the top, or things where you don’t really need a user control if a nice helper method or macro would do.
August 11th, 2008 at 8:13 am
I don’t know about user controls, but as far as ViewComponents go, we have a MenuComponent that renders a navigation menu based off of categories. The ViewComponent can contain logic (just like a controller) and uses the ICategoryRepository to build a navigation menu.
When we use it, we don’t have to worry about which dependencies it needs — we simply add a reference to it to our page and it does its magic. I don’t think you could get that same functionality with just a partial file.
August 11th, 2008 at 6:05 pm
Yeah, even if it was possible that sort of dependency and data acquisition is probably best kept out of the views. It would be more difficult to unit test and would put the code at risk when you’re making changes to the html.
That said it could be possible to provide a mechanism to move the view class instantiation up a few levels instead of the direct call to Activator.CreateInstance(type). That could give the view engine the chance to use an inversion of control container to instantiate the view.
That way if the partial could add a ICategoryRepository CatRepos {get;set;} to the class, then windsor would provide an instance and the view could use it like [var cat="CatRepos.GetCategory(catname)"/]
Of course just because you can do something doesn’t mean you should. :) It could start to feel too much like code-behind.
August 21st, 2008 at 8:16 am
Thanks for adding this, it’s a pretty pretty powerful feature.
The partial support in Spark is great :)