Sunday 28 June 2009

EPiServer Composer - How to figure out which content function is first (or last) within a content area

In my previous post (EPiServer-based site in 4 weeks?) I have presented number of quite high level thoughts regarding our last EPiServer project. In this and a few forthcoming post I would like to focus more on technical details and present several more interesting EPiServer Composer (version 3.2.5) use cases.

How to figure out which content function is first (or last) within a content area.

Imagine following piece of user interface:


It's an area where editors can define four arbitrary components. Components can be a text, image + text or just an image. Here is a typical html for this use case:

   1:  <div class="options">
   2:     <div class="option first"> ... </div>
   3:     <div class="option"> ... </div>
   4:     <div class="option"> ... </div>
   5:     <div class="option last"> .... </div>
   6:  </div>

Div with class options is a wrapper for all components. Each component has a class option. Quite typically in situation like this, first and last elements are a bit different. Depending on site design it's required to add some visual effects and that is why additional classes are added to the first and last element. This is very flexible approach as changes in html are minimal and final visual effect depends fully on CSS.

The problem for developer is that EPiServer Composer allows to simply drag and drop any number of content functions and each function is fairly autonomous. Content function is responsible for displaying html, it has no knowledge about context in which it was used. It doesn't know anything about content area to which it belongs, also it doesn't know anything about other content functions within the same content area. That is why to get information about context you need to operate one level above the functions.

But firstly, each content function need to implement following interface:

   1:  public interface IListItemPosition
   2:  {
   3:      bool IsLastElement { get; set; }
   4:      bool IsFirstElement { get; set; }
   5:  }

And now tricky part - changes on the higher level. A few things need to be added to the page/class which inherits from ExtensionBaseTemplate.

You need to override OnInit method:

   1:  protected override void OnInit(EventArgs e)
   2:  {
   3:      CurrentExtensionPageHandler.LoadContentArea += CurrentExtensionPageHandler_LoadContentArea;
   4:      CurrentExtensionPageHandler.LoadContentFunction += CurrentExtensionPageHandler_LoadContentFunction;
   5:  
   6:      base.OnInit(e);
   7:  }
Above code adds our handlers to the following events:
  • LoadContentArea - this way we will get information about all available content areas and what is more important - count of content functions for each area!
  • LoadContentFunction - Composer fires this event for each content function. Having a total number of content functions for each area we can easily detect first and last elements.

Here are implementations for the handlers:

   1:  #region ContentAreaFunctionCounter
   2:  
   3:  protected ContentAreaFunctionCounter ContentAreaFunctionCounter = new ContentAreaFunctionCounter();
   4:  
   5:  protected void CurrentExtensionPageHandler_LoadContentFunction(object sender, ExtensionPageEventArgs e)
   6:  {
   7:      var element = e.ContentFunction as IListItemPosition;
   8:      if (element == null) return;
   9:      
  10:      element.IsFirstElement = IsFirstElement(e);
  11:      element.IsLastElement = IsLastElement(e);
  12:  }
  13:  
  14:  private static bool IsFirstElement(ExtensionPageEventArgs e)
  15:  {
  16:      return e.ContentArea.Controls.Count == 0;
  17:  }
  18:  
  19:  private bool IsLastElement(ExtensionPageEventArgs e)
  20:  {
  21:      var numberOfElements = ContentAreaFunctionCounter.GetContentAreaFunctionCount(e.ContentArea.ID);
  22:      return e.ContentArea.Controls.Count == (numberOfElements - 1);
  23:  }
  24:  
  25:  protected void CurrentExtensionPageHandler_LoadContentArea(object sender, ExtensionPageEventArgs e)
  26:  {
  27:      var functionsCount = e.ContentAreaData == null ? 0 : e.ContentAreaData.ContentFunctions.Count;
  28:      ContentAreaFunctionCounter.SetContentAreaFunctionCount(e.ContentArea.ID, functionsCount);
  29:  }
  30:  
  31:  #endregion

Missing part is class ContentAreaFunctionCounter which is responsible only for keeping information about available content areas and functions count:

   1:  public class ContentAreaFunctionCounter
   2:  {
   3:      private readonly IDictionary<string, int> contentAreaFunctionCount = new Dictionary<string, int>(); 
   4:      
   5:      public void SetContentAreaFunctionCount(string contentArea, int functionCount)
   6:      {
   7:          contentAreaFunctionCount[contentArea] = functionCount;
   8:      }
   9:  
  10:      public int GetContentAreaFunctionCount(string contentArea)
  11:      {
  12:          if (contentAreaFunctionCount.ContainsKey(contentArea))
  13:          {
  14:              return contentAreaFunctionsCount[contentArea];
  15:          }
  16:  
  17:          return 0;
  18:      }
  19:  }

I would recommend creating a base class encapsulating this functionality. Each content function which needs to be aware of it's position just need to implement the IListItemPosition interface. And that's it! :)

If it's necessary you can easily extend IListItemPosition interface to contain int Position {get; set;} property and this way give all functions idea about it's position (not just first and last one).

27 comments:

Orvar said...

Nice post Marek!

Jon Roberts said...

Is it possible to get content out of a composer block for an RSS (.ashx) feed using FindPagesWithCriteria - then loop through all pages getting the content out of a particular block?

Unknown said...

Superb i really enjoyed very much with this article here. Really its a amazing article i had ever read. I hope it will help a lot for all. Thank you so much for this amazing posts and please keep update like this excellent article.thank you for sharing such a great blog with us. expecting for your updation.
Digital Marketing Company in Chennai

swathi said...

Really i like this blog and i got lot of information's from your blog.And thanks for sharing!!!!
Agaraminfotech
Human resources management software
cctv camera installation in Chennai
RFID Solutions

Unknown said...

This information is impressive.I am inspired with your post writing style & how continuously you describe this topic.


seo company

Unknown said...

Super i am really enjoyed very much with this article here.

Python Training

Unknown said...

This information is impressive.


Hadoop Training in Chennai

Stanly said...

It is really a great and useful piece of info. I’m glad that you shared this helpful info with us. Please keep us informed like this. Thank you for sharing.


Dental Hospital in Chennai
Full Mouth Dental Implants in Chennai
Kids Dental Care in Chennai
Cosmetic Dental Clinic in Chennai

Unknown said...

It's really an Excellent post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog. Thanks for sharing.
Best Root Canal Treatment in Delhi
Best Dental Clinic in Delhi

JP said...

This is truly enjoyable. I loved it very much.

Best Dental Hospital in Chennai | Best Dental Implant in Chennai | Best Rhinoplasty Surgeon in India | Cosmetic Dentistry | Root Canal Treatment in Chennai

htop said...

thanks for sharing this information
aws training center in chennai
aws training in chennai
best python training in chennai
selenium training in chennai
selenium training in omr
selenium training in sholinganallur

Ankit Ron said...

Nice idea thank you
you Can play daily online ,live cricket games,cricket online games,best cricket games,play cricket online, cricket game online at best cricket games app for android phones.
play cricket online

AlanBarlow said...

Thanks for sharing. This is something very new for me. Be sure to check below:
custom logo design company

Keming Plastic Co., Ltd said...

Interesting stuff to read. Keep it up. Waterproof pvc fabric / fishing waders / raincoats / PVC Tarpaulin / PVC Film Manufacturers

Nio Smart said...

Thanks for sharing..Really Great Post...

School ERP Software Company in Pune

mir said...

this is really a helpful & useful article thanks for sharing it with us.
we design the best websites & logos with a discount also with a guarantee are you interested?
Logo Designers

Dinesh said...

Nice Blog thanks for sharing information..

Are you fond of music? But you spend most of the time-traveling in the car? No worry, we are here with a range of Best Car Music System by SONY which will help you enjoy your favourite Singers even when traveling in the car.
Sony DSX-B700 Digital Media Receiver with Bluetooth

khusi choudhary said...

THANKS FOR THIS AMAZING BLOG
THANKS FOR THIS MEANING FULL ARTICLE

mik said...

This post provides clear idea designed for the new visitors of blogging, that genuinely how to do blogging and site-building.
buy MDMA Powder Crystal high Quaility 87% pure online USA

vikas said...

Thanks for this post !!

Haris said...

Thank you for sharing it with us,
it is a very unique and helpful article for us.

Buy law essay

Denver Property Management said...

Amazing article

denver property management

Karpagam Academy of Higher Education said...

Informative blog. Thanks for sharing such detailed blog. Visit our blog, you may like it.
Top MBA College In India

Emily Anders said...

Thanks for sharing an interesting and very useful blog. I always appreciate the quality content. There is a great mixture of details. keep posting. Visit here

Sehatapni said...

All about exam preparation, MCQs, Short Question Answers, Up-to-date papers, Subjective. If you are confused about exam preparation, we are here to remove all your confusion. This difficulty can only be removed if you have reliable source of knowledge. We are offering a wide range of easy ways to get good marks in exam. general knowledge mcqs, notes for matric, intermediate notes, essay, essay writing, 9th class physics notes
allama iqbal essay english

Digital Nail Art Printer India said...

Nail art salon in Indian - O'2 Nails India
Nail art salon in Delhi - O'2 Nails salon in Delhi

Appwars Technologies Pvt. Ltd. said...

Excellent Blog

Thanks for this wonderful blog it is very useful content for us. Visit my website to get best Information About Data Science Training in Noida and mention Below Technologies.

Python Training in Noida
Data Science Training in Noida
java Training in Noida
full stack Development Training institute in Noida
Software Testing Training in Noida
Summer Training in noida
Web Development Training in Noida