-
SPEAK: ItemTreeView with multiple Roots
April 22, 2016 Rodrigo Peplau 0
I’ve being studying SPEAK recently for a module I’m building, and it’s being a lot of fun so far. Of course, when learning anything that imposes a different paradigm, it’s common to get stuck with “simple” things that, in another programming realities, are easy to accomplish.
And then it happened to me: the ItemTreeView component offers exactly the UI experience I want to provide. It lists Sitecore items in a Tree, just like the Content Editor, but also offers a way for the user to select items with checkboxes. That is perfect, but there’s one problem: you can only have one single Root for each ItemTreeView component.
This limitation simply made impossible one requirement I have, which is to list a certain Template and all their fields and Standard Values (Ok) along with all their Base Templates (impossible). Since we can’t predict how many Base Templates (if any) a certain template has, we can’t simply add one or two ItemTreeViews to the SPEAK page and expect they will cover all your needs. Instead, we need to be able to dynamically add multiple Roots to an ItemTreeView. But how?
First Try – Google
As a good boy I first asked Google, but looks like SPEAK components are not yet very widely being subjects of debates in forums and communities worldwide. Most of the documentation are introductory step-by-steps, along with the official documentation which is well descriptive, but not very detailed in terms of what you can do with a certain SPEAK component. Nothing really targeting the ItemTreeView component in general, or my need of having multiple Roots in specific.
Second try – Sitecore Community
For those who don’t know yet, the new Sitecore Community website, built on top of Zimbra/Telligent Community, is the main resource for trading Sitecore experiences. After a quick search, I also see no entries discussing what I needed, and then decided to start up my own question topic: “ItemTreeView with SPEAK : Having multiple RootsItems? Dynamically adding a new one? (with C#)”
Again nothing came out from that topic, so I started to think this may be a good thing to contribute, and at the same time to achieve what I’m trying to have in my component. This post brings the whole solution, along with a Sitecore package with the final code and items that you can download and use.
Ok, nevermind, I’ll build my own
The ItemTreeView component does not support multiple roots out-of-the-box, so I ended up solving this issue by creating a new version of the ItemTreeView component that does it.
Looking the original ItemTreeView component (core:/sitecore/client/Business Component Library/version 1/Layouts/Renderings/Lists and Grids/ItemTreeView) brought me to its View file (\sitecore\shell\client\Business Component Library\Layouts\Renderings\ListsAndGrids\TreeViews\ItemTreeView.cshtml).
These are the important parts we want to pay a special attention:
- Line 17 – It’s where the rootId configured by the user is taken:
var rootItemId = userControl.GetString("RootItem");
- Lines 56 to 65 – RootId is used to retrieve the real Sitecore item:
Item rootItem = null; if (!string.IsNullOrEmpty(rootItemId)) { rootItem = database.GetItem(rootItemId, Language.Parse(contentLanguage)); } if (rootItem == null) { rootItem = database.GetRootItem(); }
- Lines 67 to 69 – The TreeView component is setup with the Root Item configured
var rootItemIcon = Images.GetThemedImageSource(!string.IsNullOrEmpty(rootItem.Appearance.Icon) ? rootItem.Appearance.Icon : "Applications/16x16/documents.png", ImageDimension.id16x16); userControl.SetAttribute("data-sc-rootitem", rootItem.DisplayName + "," + rootItem.Database.Name + "," + rootItem.ID + "," + rootItemIcon); userControl.SetAttribute("data-sc-rootitempath", rootItem.Paths.Path);
- Lines 86 to 88 – The div container is output with its configurations
<div @htmlAttributes> <ul></ul> </div>
My first experience were to duplicate the div markup, so I had it twice:
<div @htmlAttributes> <ul></ul> </div> <div @htmlAttributes> <ul></ul> </div>
This ended up showing two identical roots – and the “twin” root worked perfectly. That was the confirmation I needed to create an improved version of the ItemTreeView component that can spit multiple roots. With the goal of simplicity, my component will act the same as the original ItemTreeView, but its “RootItem” property now will accept not just one, but multiple IDs (in a pipe-delimited string).
Here are the steps I take:
STEP 1 – Create the new component
- Duplicated the original component and gave it the name “ItemTreeView2″
- At the duplicated item, deleted the children “ItemTreeView Parameters” (we are going to use the original parameters template)
- “Parameters Template” field – it should stay poiting to the original (Client/Business Component Library/version 1/Layouts/Renderings/Lists and Grids/ItemTreeView/ItemTreeView Parameters)
- At the “Path” field I made it point to my new View file: /sitecore/shell/client/Business Component Library/Layouts/Renderings/ListsAndGrids/TreeViews/ItemTreeView2.cshtml
STEP 2 – Make it accept multiple Roots
- Comment the original line:
//var rootItemId = userControl.GetString("RootItem");
- Add our new logic:
var rootItemIds = userControl.GetString("RootItem").Split('|'); var rootItemId = rootItemIds.FirstOrDefault();
Most of the original component will stay as is, and the first Root will be handled exactly how it is natively done.
STEP 3 – Make it spit the other Roots
- At the very bottom of the View, we are going to create a new list of HtmlAttributes, which is here used to represent the Tree setup:
@{ var lstAttributes = new List<HtmlString>(); for (var i = 1; i < rootItemIds.Length; i++) { rootItem = null; if (!string.IsNullOrEmpty(rootItemId)) { rootItem = database.GetItem(rootItemIds[i], Language.Parse(contentLanguage)); } if (rootItem == null) { rootItem = database.GetRootItem(); }
rootItemIcon = Images.GetThemedImageSource(!string.IsNullOrEmpty(rootItem.Appearance.Icon) ? rootItem.Appearance.Icon : "Applications/16x16/documents.png", ImageDimension.id16x16); userControl.SetAttribute("data-sc-rootitem", rootItem.DisplayName + "," + rootItem.Database.Name + "," + rootItem.ID + "," + rootItemIcon); userControl.SetAttribute("data-sc-rootitempath", rootItem.Paths.Path); lstAttributes.Add(userControl.HtmlAttributes); } }
- And then have the loop for the HTML container:
@foreach (var htmlAttr in lstAttributes) { <div @htmlAttr> <ul></ul> </div> }
And that’s all!
Now I can add a pipe-delimited list of IDs, either by adding it tothe rendering setup or by using my PageCode file:
TreeDsBaseTemplates.Parameters["RootItem"] = String.Join("|", ComponentItem.DatasourceTemplate.BaseTemplates.Select(p => p.ID.ToString()).ToArray()); TreeDsBaseTemplates.Parameters["Database"] = ComponentItem.DatasourceTemplate.Database.Name;
This way my module now has two ItemTreeViews: first is a normal (native) one, the other is my extended control with roots being dynamically added:
The package
Here is the resulting package of the new ItemTreeView2 SPEAK component. Fell free to download and use it!
Enjoy!
Categories: Development, SPEAK
Mass data processing with Rules and Actions - The Sitecore Rule Processor Module Faster Sitecore for Development - All in a single include
- Line 17 – It’s where the rootId configured by the user is taken:
Proudly 10x Sitecore MVP!
(2016-2025)
Localization
Recent Posts
Recent Comments
- navan on Meet MVPinny: the AI-Powered Sitecore Assistant
- Adriana on Content generation with Sitecore Connect and ChatGPT
- NAVAN on Automatic Sitecore NuGet upgrades with Powershell
- Hedipo S Menezes on Corey Peplau wrote this - WFFM conflict with Unity DI and a lesson on how Sitecore community is so amazing
- Rodrigo Peplau on ERROR [Content Testing]: Cannot find PhantomJS executable at ' (...) /data/tools/phantomjs/phantomjs.exe'. Aborting screenshot generation.
Archives
- March 2025
- January 2025
- June 2024
- April 2024
- February 2024
- December 2023
- November 2023
- August 2023
- July 2023
- January 2023
- February 2022
- December 2021
- November 2021
- March 2021
- July 2020
- February 2020
- September 2019
- July 2019
- April 2019
- March 2019
- December 2018
- February 2018
- January 2018
- November 2017
- September 2017
- August 2017
- July 2017
- March 2017
- February 2017
- November 2016
- September 2016
- August 2016
- July 2016
- April 2016
- November 2015
- September 2015
- July 2015
- April 2015
- March 2015
- February 2015
Categories
- Actions
- Active Directory
- Analytics
- Architecture
- Bug fixing
- CDP/Personalize
- ChatGPT
- Content Edition Experience
- Content Hub
- Continuous Integration
- Dev
- Development
- Environments
- Experience Editor
- Experience Forms
- Front-end
- Hackathon
- Health Check builds
- Helix
- How To
- LDAP
- MVP
- MVP Summit
- MVPinny
- Phantom JS
- Powershell
- QA
- Richtext Editor
- Rules
- Security Provider
- SIF
- Sitecore 9
- Sitecore API
- Sitecore Community
- SItecore Connect
- Sitecore Modules
- Sitecore Rocks
- Sitecore Rule Processor
- Sitecore Symposium
- SPE
- SPE-only Alliance
- SPEAK
- SUG
- Support Ticket
- TDS
- Team City
- Uncategorized
- Upgrades
- Visual Studio
- WFFM
- Workflow
- XConnect
- xDB
- XM Cloud