Saturday, 20 February 2010

Partials in Spark View Engine

Continuing my journey with Spark, the next natural stop for me after the basics was “partials”. I am a uber-fan of DRY (almost fanatical) so was keen to try and cut down the dupe of HTML etc. I thought I would share the “partials basics” for both you and me :)

What Are “Partials”?

“Partials” are basically snippets of HTML/”code” markup that can be used throughout your MVC application. This reduces code duplication and helps keep your site maintainable. It can also make your markup easier on the eyes, since you can isolate chunks of markup into “units of functionality” (e.g. a “navigation bar”).

What Are Partials NOT?

UserControls. People often relate/confuse partials with user controls, and they are NOT. While UserControls can encapsulate HTML, code behind, events and be packaged into assemblies etc. Partials are still (or at least should) be pretty “dumb” views.

Why Use Partials (and MVC) When UserControls Do More?

If you are more interested in mashing up code with markup etc, then MVC is probably not for you. MVC is about clean separation of concerns and good design. Partials don’t have code because Views shouldn’t have code (other than the absolute minimum, e.g. for-each).

How Do I Use Partials in Spark?

Naming Conventions

Another reason I like Spark is because it reinforces the idea of “convention over configuration”. We shouldn’t need things like XML and additional markup if we establish a standard and stick to it.

In short, put Partials in your “Views\Shared” folder and prefix them with an underscore (e.g. “_MyPartial.spark”). This identifies to Spark that the markup is actually a partial.

Not-Recommended Syntax (RenderPartial)

Pretty explicit syntax, but not recommended:

   1: <render partial="_MyPartial" />

Preferred Syntax

This is the recommended way to use a partial:

   1: <MyPartial />

Note here that we just use the partial name (without the underscore prefix) and it all “just works”.

Injecting Variables in to Partials

So, we have referenced our partial – how to we get data in to them?

   1: <partialName variableName="value" />

And the partial markup (to use the variable):

   1: <p>
   2:   String Variable: ${myString} <br />
   3:   Integer Variable: ${myInt}
   4: </p>

Note here we are not explicitly setting types – it all kind of “just works” for 99% of the times. Just be careful with any specific formatting requirements (this should in theory be handled by your model).

Model Data

It is actually recommended that you actually get required model data in the parent view, not the partial and then pass that value to the partial. This ensures that the partial fails if you do not pass in from the top. This is very similar to “dependency injection” as well as remove “smarts” from the partial.

In the view that uses the partial:

   1: <viewdata model="SomeType" />
   2: <MyPartial user="Model" />

See? We are passing in the “model” data as a variable – meaning the partial is less tightly bound to the implementation.

We can then access the model data in the partial by using the variable like so:

   1: <h2>${user.Name}</h2>
   2: <ul>
   3:     <li>T: ${user.Phone}</li>
   4:     <li>E: ${user.Email}</li>
   5: </ul>

The partial is focused on rendering the view data passed to it (a “user”) as opposed to retrieve it from ViewData/Model.

Complex Objects

Used in exactly the same way as above – just pass the object as a variable to the partial.

The key thing to note here is that the view take no requirements on the view (i.e. we don’t need to “type” them) we just use the “dollar syntax” to access a property and assume it is there. If anything is amiss, things will blow up. This sounds bad, but the truth is this – your views should be so dumb they literally do nothing.

For example, some people ask “what if the object is null?” – well, I would ask “What if the object is null? What does that mean in terms of business rules? Why isn’t that reflected in the ViewModel that is returned from the service/model layer? Record not found you say? Why didn’t you (or your model) tell me that?”.

In Summary

  • Views should be simple/stupid, Spark directly supports/reinforces that.
  • I (personally) find the Spark syntax very clean and intuitive.
  • If you are wanting your views to be “smarter” – you are doing something wrong.

No comments:

Post a Comment