Skip to content

Context Aware Blocks

nairdo edited this page Dec 9, 2013 · 12 revisions

This section has some pretty advanced stuff that's also pretty abstract, but if you're up for the challenge, you'll learn how to take advantage of a very powerful feature in the framework.

NOTE: Show Chip the Lobster in a "thinking" pose.

It's easy to hard-code some functionality that operates against a very particular Entity type. But what would you do if that functionality could really apply to various kinds of Entities? For example, the Note entity in Rock can be used against a Person, a Group, a PrayerRequest, etc. Wouldn't you like to develop the "Note" BlockType so that it could work against any of those entities? If this sounds interesting, continue reading; otherwise you can just skip this section.

Sometime it's advantageous to create a BlockType that can provide some functionality for a variety of other entities, or provide some functionality for any instance of a particular entity without the need to worry about which particular instance. Adding the [ContextAware] decoration attribute to your block will give it the ability use the entity that is in the "Context". In other words, your block can pluck an instance of an entity out of this "context" and use it for whatever it wants.

The attribute can be used in one of two ways. If your block can support context for any type of entity, you'd just decorate it with the [ContextAware] attribute without any parameter as shown here:

using Rock.Web.UI;

namespace RockWeb.Blocks.Core
{
    /// <summary>
    /// User control for editing the value(s) of a set of attributes for a given entity and category
    /// </summary>
    [ContextAware]
    [TextField( 1, "Entity Qualifier Column", "Filter", "The entity column to evaluate when determining if this attribute applies to the entity", false, "" )]
    [TextField( 2, "Entity Qualifier Value", "Filter", "The entity column value to evaluate.  Attributes will only apply to entities with this value", false, "" )]
    [TextField( 3, "Attribute Categories", "Filter", "Delimited List of Attribute Category Names", true, "" )]
    [TextField( 4, "Xslt File", "Behavior", "XSLT File to use.", false, "AttributeValues.xslt" )]
    public partial class AttributeCategoryView : RockBlock

Then, when you add an instance of your block to a page, the framework will automatically add a Block Attribute in order to allow the user-admin to set the type of entity that is providing context.

If your block only supports a specific entity type, you can specify the type in the [ContextAware] attribute like this:

namespace Rock.Web.UI
{
    /// <summary>
    /// A Block used on the person detail page
    /// </summary>
    [ContextAware( typeof(Person) )]
    public class PersonBlock : RockBlock

In this case, user-admin configuration for the block is unnecessary since the block only supports a single entity type.

Inform the Page About the Context Parameter

Whenever a context aware block is added to a page, the page also needs to know what page parameter to use for loading the context object. After configuring the block, edit the page properties for the page. The Advanced Settings area will now display a configuration field for each context object used by blocks on the page. You need to specify the page parameter that contains the id for the object(s) to be loaded for context.

Using the Context

The page and framework are responsible for putting the necessary entities into the context when appropriate.

Continuing with the previous example of a block that is context aware of a Person entity, in order to obtain the actual person in the context, the block will fetch it from its ContextEntity for the appropriate type as shown here:

    Person = this.ContextEntity<Person>();
    if ( Person == null )
    { // throw error or handle as appropriate.

Now your block has a particular Person and didn't need to concern itself with how that person got into the "context".

Clone this wiki locally