SharePoint 2010 Page Components in Sandboxed Solutions
Development, JavaScript, Sandbox, SharePoint 2010, Tips & Tricks
SharePoint 2010 ships with the new Ribbon framework that allows you to easily extend the Ribbon with new functionality. All Ribbon extensions consist of the UI and behavior, which in simple scenarios can be specified declaratively but in more advanced scenarios would rely on a Page Component. Most samples, that show using Page Components, suggest registering them using Delegate Controls. Unfortunately this makes it impossible to use Page Component in Sandboxed Solutions which don’t support Delegate Controls. So are we forced to use the limited declarative approach or is there a solution that would allow us to register custom Page Components within Sandboxed Solutions?
CommandUIHandler vs. Page Component
If you’re interested in extending the SharePoint 2010 Ribbon with some new functionality you have to take care for two things. First of all you have to register your control: no matter if it’s a custom tab, group or a button. The next step is to associate some behavior with your control. You can do this the simple way using a CommandUIHandler or a more complex way using a Page Component. Andrew Connell wrote recently an article about advantages of using custom Page Components. As the background case Andrew uses extending the Ribbon from code – something you are very likely to do if the extension applies to a specific piece of the solution only.
A little different approach on using Page Components has been discussed by Chris O’Brien, while he creates globally available extensions. In his example Chris uses a Delegate Control to register the Page Component across the whole Site Collection. As you might’ve heard by now, Delegate Controls are not supported in Sandboxed Solutions. So does this mean that if you’re writing a globally available Ribbon extension you cannot use Page Components or is there a different way to register the behavior than using a Delegate Control?
Registering Page Components using JavaScript
Recently I’ve created a few Web Content Management-oriented Ribbon extensions. In many situations the extension itself would easily fit into the capabilities available for Sandboxed Solutions. Unfortunately, because I needed to use Page Components, I had to fall back to Delegate Controls and change the Solution to a Farm Solution. Not convinced about the Delegate Control being the only way to register a Page Component, I’ve done some experiments.
What is exactly the challenge with registering Page Components?
Registering a Page Component means nothing more than calling its initialize function. While it might seem trivial at first it isn’t and here is why…
Page Components rely on some resources which are being dynamically loaded by SharePoint. Those are the SP.js, CUI.js and the SP.Ribbon.js files but also the MicrosoftAjax.js file. All of those are being loaded on demand to improve the User Experience. For you – as a Ribbon-extension developer – it means that you cannot just assume that those files have already been loaded and have to check it and sometimes even load them yourself.
When using a Delegate Control you can do all the checks as easy as adding two ScriptLink controls just before initiating the Page Component:
<SharePoint:ScriptLink Name="CUI.js" LoadAfterUI="true" OnDemand="false" Localizable="false" runat="server" ID="ScriptLink1" />
<SharePoint:ScriptLink Name="/_layouts/Mavention/Mavention.SharePoint.Ribbon.PageComponent.js" LoadAfterUI="true" OnDemand="false" Localizable="false" runat="server" ID="ScriptLink2" />
<script type="text/javascript">
//<![CDATA[
function initRibbon() {
Mavention.SharePoint.Ribbon.PageComponent.initialize();
}
SP.SOD.executeOrDelayUntilScriptLoaded(initRibbon, 'Mavention.SharePoint.Ribbon.PageComponent.js');
//]]>
</script>
But how to achieve the same if the only thing available to you is the CustomAction element?
Registering Page Components in Sandboxed Solutions
It turns out that you can register a Page Component using the following JavaScript snippet:
SP.SOD.executeOrDelayUntilScriptLoaded(function () {
SP.SOD.executeOrDelayUntilScriptLoaded(function () {
var ctx = SP.ClientContext.get_current();
var site = ctx.get_site();
ctx.load(site);
ctx.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
var pageComponentScriptUrl = SP.Utilities.UrlBuilder.urlCombine(site.get_url(), "Style Library/Mavention/Mavention.SharePoint.Ribbon.PageComponent.js");
SP.SOD.registerSod('mavention.sharepoint.ribbon.pagecomponent.js', pageComponentScriptUrl);
LoadSodByKey('mavention.sharepoint.ribbon.pagecomponent.js', function () {
Mavention.SharePoint.Ribbon.PageComponent.initialize();
});
}));
}, "cui.js");
}, "sp.js");
The first thing that I mentioned was the dependency of the Page Components on SP.js and CUI.js files. We can solve this by using the SP.SOD.executeOrDelayUntilScriptLoaded function (1, 2). Since both files are loaded by SharePoint itself all we have to do is wait until they have been loaded. The dependency on the MicrosoftAjax.js file is being handled by SharePoint itself, as its required by the SP.js file.
The next step is to load our custom Page Component. As mentioned before this can be done not earlier than after the SP.js and MicrosoftAjax.js files have been loaded and this is exactly why using a CustomAction is not an option. Another challenge is getting a correct URL of the JavaScript file that contains the definition of our Page Component. Since the file has been deployed to the Style Library or any other Document Library in the root site, we need the URL of the current Site Collection to prepend the part of the URL that we know (3-6).
Once we have the Site Collection URL we can build up the URL of the script containing the definition of our Page Component. While you could do that manually, it’s probably easier and more reliable to use the SharePoint ECMA script URL Builder (7). Using that URL we can register our script to be loaded dynamically (8). The next step is to actually load the file. Unfortunately I haven’t found a method to do this that would be a part of the public SP ECMA API, and had to use the internal LoadSodByKey function. The LoadSodByKey function takes two arguments. The first is the key of a script previously registered using the SP.SOD.registerSod function.
Important: The key of the registered script must be lower case. Although it doesn’t matter which case you use while registering the script in the SP.SOD.registerSod function, internally it’s being converted to lower case. Unfortunately the LoadSodByKey function doesn’t automatically convert the key to lower case so if you use casing other than lower case your script won’t be loaded.
Finally, once the custom Page Component has been loaded, we can move on and initialize it calling the initialize function.
Summary
Using Page Components for implementing behavior of custom Ribbon extensions gives you more control and allows you to support advanced scenarios. Although it seems that the only way for using Page Components for globally available extensions is by using Delegate Controls, you can use a pure JavaScript-based approach to achieve the same. This allows you to use Page Components in Sandboxed Solutions.




May 31st, 2011 at 8:06 am
I want to create four tab ribbon for a content/publishing page in Sandbox solution.I created the structure of ribbon but i don't get any solution to show my ribbon on a particular page.Can you suggest me that how can i show my ribbon on a page in sandbox environment because sandbox have own limitation you know so i can't use web part,user control etc.
May 31st, 2011 at 9:16 am
@Darpan: If everything is correct your page already should have the Ribbon on it and by activating the Feature your components should become available on the Ribbon. What else are you trying to achieve?
May 31st, 2011 at 11:32 am
Thanx for response.Yes,you are right that my page already have Ribbon but my custom Ribbon Tab which structure is in Element.xml . So, when i deploy my wsp the page with ribbon is shown but ribbon have default browse and page tab not my custom tab and my custom tab is available by using Four approach that i got till now research on SP Ribbon but that for approach only work in farm solution not in sandbox solution.If you have idea about how to make available custom tab on a page in sandbox then please help me.
The four approach that i know are:
• Delegate Control – “You might’ve heard by now, Delegate Controls are not supported in Sandboxed Solutions” saying by you.
• Using WebPart – We all know that there are no GAC deployment in sandbox solution so some assemblies we need to be deploy at GAC are not deploy to GAC.
• Using Server Control – For server control, we need a full trusted mode which are not available in sandbox solution.
• Using JQuery – This approach is not working. You can see this approach on this Link (http://ikarstein.wordpress.com/2010/06/15/how-to-activate-sharepoint-ribbon-tab-by-javascript-code/)
May 31st, 2011 at 1:39 pm
Hi Waldek,
I am also stuck in the same issue. I am creating ribbon for the SharePoint content pages in the SharePoint 2010. The development Constraint is using SANDBOX solution in VS 2010. Well, I have followed below steps:
1. Created a VS 2010 empty project (Sandbox)
2. Added an Element->Element.xml
3. Added the design of the ribbon.
4. After that i have deployed the solution.
But the thing is that now how can I show this Custom ribbon tab with button. In Farm solution I have created the web part and used below code. Microsoft.SharePoint.WebControls.SPRibbon.GetCurrent(this.Page).MakeTabAvailable("HelpDesk.Ribbon.ServiceTab"); Microsoft.SharePoint.WebControls.SPRibbon.GetCurrent(this.Page).MakeTabAvailable("HelpDesk.Ribbon.ServiceSupportTab");
SPRibbon ServiceRequest = SPRibbon.GetCurrent(this.Page);
ServiceRequest.InitialTabId = "HelpDesk.Ribbon.ServiceTab";
ServiceRequest.CommandUIVisible = true;
ServiceRequest.Minimized = false;
But as from my understanding that I cannot use the same code in the sandbox solution.
Initial code for ribbon design is
So, the thing is that I am stuck at this stage to show the custom ribbon tabs in the Sandbox solution in the SharePoint pages. Please help me out, if you have some Idea or some solution. Then it will be very helpful for me. I have spent two weeks for that and still I have not got any solution.
Bharat Sukhwal
February 16th, 2012 at 2:33 am
Cool post! I'm developing a sandboxed solution and with your approach i will try to get the ribbions ready :)
February 22nd, 2012 at 5:31 am
Thanks,
Well please share if its possible.
Bharat Sukhwal
February 22nd, 2012 at 7:17 am
@Bharat: Although I don't have a solution now, I will definitely share if I find out anything.
March 12th, 2012 at 10:56 am
Hi Everyone,
I am also facing issues in sandbox.Custom ribbon is not showing in Pages in sandbox.
Anyone find the solution.Please share it if there is a solution.
Thanks
Karthik
March 12th, 2012 at 12:29 pm
Hi Everyone,
Anyone has find the solution for Tab in sandbox pages? I am also facing the problem but couldnot find the solution.
Thanks
Karthik
October 5th, 2012 at 2:03 pm
I have found out the solution for adding a button and use the populatequerycommand to expand the items.
I am hoping to finalize the solution this weekend and will post it on codeplex. (Module will be called 'Document Template')
January 12th, 2013 at 3:27 pm
Awesome Post! Where would I put that javascript code to be sure it is loaded correctly in visual studio? I know how the code works but I still have to deploy it with my feature and be sure it is executed correctly. My Tab loads correctly with the controls just fine, but need to do this in Sandbox.
January 12th, 2013 at 7:01 pm
Hey! I actually figured it out! Have it working fine now in sandbox and functions are firing fine!
January 14th, 2013 at 7:55 am
If you have CKS:DEV installed add a new CustomAction SPI to your project. Without add an EmptyElement and define there a Custom Action with the CustomAction element.