How to Add Custom Buttons to the SharePoint 2013 Ribbon

Written by Denis Stadler on . Posted in Development

Recently I participated in a SharePoint 2013 project, where the SharePoint 2013 Ribbon had to be customised to fulfil the following business requirements:

  • A new tab containing the specific buttons had to be created
  • Some of the buttons had to be enabled only on single/multiple items’ selection
  • Some business actions had to be performed when the buttons were clicked

ribbon-buttons

When it comes to the customisation of the SharePoint ribbon I have to say that the articles present on the MSDN web site are not enough. My recommendation would be to take a look at the following blog series (they are written for SharePoint 2010, but most of them are still valid):

Based on this, a solution compliant to the business requirements above has been developed (you can download the source code from a link present at the end of this article). It contains:

  • A simple SharePoint custom list with 2 columns: Title and Parameter
  • A SharePoint element for the Ribbon customisation
  • A Java script file that contains the commands and the enable functions of the buttons
  • A simple application page that is being opened as a modal dialog when the first button is clicked

sp-solution

The Ribbon Customisation Element File

Basically this file creates 3 buttons: 1 – One Item Selection, 2 – Multiple Items Selection, 3 – Multiple Items Selection Conditional (I think the button names are self explanatory).
ribbon-examples-multiple-selection

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
      Id="RibbonExample.CustomTab"
      Location="CommandUI.Ribbon"
      RegistrationType="ContentType"
      RegistrationId="0x01"
      >
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Tabs._children">
          <Tab Id="RibbonExample.CustomTab"
               Title="Stadler Ribbon Examples"
               Description="TO DO: Add Description here"
               Sequence="400">
            <Scaling Id="RibbonExample.CustomTab.Scaling">
              <MaxSize Id="RibbonExample.CustomTab.Group1.MaxSize"
                       GroupId="RibbonExample.CustomTab.Group1"
                       Size="RibbonExample"/>
              <Scale Id="RibbonExample.CustomTab.Group1.Scaling.CustomTabScaling"
                     GroupId="RibbonExample.CustomTab.Group1"
                     Size="RibbonExample" />
            </Scaling>
            <Groups Id="RibbonExample.CustomTab.Groups">
              <Group
                  Id="RibbonExample.CustomTab.Group1"
                  Description="TO DO: Add Description here"
                  Title="Different Operations"
                  Sequence="30"
                  Template="Ribbon.Templates.RibbonExamplesTemplate">
                <Controls Id="RibbonExample.CustomTab.Group1.Controls">
                  <Button
                    Id="RibbonExample.CustomTab.Group1.Button1"
                    Command="RibbonExample.Command.CommandButton1"
                    Sequence="10"
                    Image16by16="/_layouts/15/images/Ribbon.Examples/Process16.png"
                    Image32by32="/_layouts/15/images/Ribbon.Examples/Process32.png"
                    Description="TO DO: Add Description here"
                    LabelText="One Item Selection"
                    TemplateAlias="Custom1"/>
                  <Button
                    Id="RibbonExample.CustomTab.Group1.Button2"
                    Command="RibbonExample.Command.CommandButton2"
                    Sequence="20"
                    Image16by16="/_layouts/15/images/Ribbon.Examples/Process16.png"
                    Image32by32="/_layouts/15/images/Ribbon.Examples/Process32.png"
                    Description="TO DO: Add Description here"
                    LabelText="Multiple Items Selection"
                    TemplateAlias="Custom2"/>
                  <Button
                    Id="RibbonExample.CustomTab.Group1.Button3"
                    Command="RibbonExample.Command.CommandButton3"
                    Sequence="30"
                    Image16by16="/_layouts/15/images/Ribbon.Examples/Process16.png"
                    Image32by32="/_layouts/15/images/Ribbon.Examples/Process32.png"
                    Description="TO DO: Add Description here"
                    LabelText="Multiple Items Selection Conditional"
                    TemplateAlias="Custom3"/>
                </Controls>
              </Group>
            </Groups>
          </Tab>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Templates._children">
          <GroupTemplate Id="Ribbon.Templates.RibbonExamplesTemplate">
            <Layout Title="RibbonExample" LayoutTitle="RibbonExample">
              <Section Alignment="Top" Type="OneRow">
                <Row>
                  <ControlRef DisplayMode="Large" TemplateAlias="Custom1" />
                  <ControlRef DisplayMode="Large" TemplateAlias="Custom2" />
                  <ControlRef DisplayMode="Large" TemplateAlias="Custom3" />
                </Row>
              </Section>
            </Layout>
          </GroupTemplate>
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
            Command="RibbonExample.Command.CommandButton1"
            EnabledScript="javascript:RibbonExample.Commands.eButton1();"
            CommandAction="javascript:RibbonExample.Commands.cButton1();" />
        <CommandUIHandler
            Command="RibbonExample.Command.CommandButton2"
            EnabledScript="javascript:RibbonExample.Commands.eButton2();"
            CommandAction="javascript:RibbonExample.Commands.cButton2();" />
        <CommandUIHandler
            Command="RibbonExample.Command.CommandButton3"
            EnabledScript="javascript:RibbonExample.Commands.eButton3();"
            CommandAction="javascript:RibbonExample.Commands.cButton3();" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
  <CustomAction
    Id="RibbonExample.Command.Script1"
    Location="ScriptLink"
    ScriptSrc ="/_layouts/15/Ribbon.Examples/ProcessCommand.js"/>
</Elements>

The Java Script File

This file is defining 6 main functions (2 for each button: enable, command). These functions are used in the Element XML file.

window.RibbonExample = window.RibbonExample || {};

RibbonExample.Commands = function () {

    enabledButton1 = function () {
        //get context
        var ctx = SP.ClientContext.get_current();

        //get all selected list items
        var selectedItems = SP.ListOperation.Selection.getSelectedItems(ctx);

        var number = selectedItems.length;

        if ((number > 1) || (number < 1)) {
            return false;
        }

        return true;
    },

    enabledButton2 = function () {
        //get context
        var ctx = SP.ClientContext.get_current();

        //get all selected list items
        var selectedItems = SP.ListOperation.Selection.getSelectedItems(ctx);

        var number = selectedItems.length;

        if (number <= 1) {
            return false;
        }

        return true;
    },

    enabledButton3 = function () {
        //get context
        var ctx = SP.ClientContext.get_current();
        //get list id
        var listId = SP.ListOperation.Selection.getSelectedList();
        //get all selected list items
        var selectedItems = SP.ListOperation.Selection.getSelectedItems(ctx);

        var number = selectedItems.length;
        if (number < 1) {
            return false;
        }

        //get selection
        var items = getSelectedItems(ctx, listId, selectedItems);
        console.log('The items have the parameter:');

        //check the value of the field Parameter in every item
        //if the selection contains an item that has another value then p returns false
        for (var i = 0; i < items.length; i++) {
            var p = items[i].get_item('Parameter');
            console.log(p);

            if (p != "B") {
                return false;
            }
        }

        return true;
    },

    getSelectedItems = function (context, listId, selectedItemIds) {
        var list = context.get_web().get_lists().getById(listId);
        context.load(list);

        var listItems = [];

        for (idx in selectedItemIds) {
            console.log(selectedItemIds[idx].id);
            var item = list.getItemById(parseInt(selectedItemIds[idx].id));
            listItems.push(item);
            context.load(item);
        }

        context.executeQueryAsync(OnSuccess, OnError);

        function OnSuccess() {
            console.log('The current number of selected items is ' + listItems.length);

            //this is triggering the ribbon refresh
            RefreshCommandUI();
        }

        function OnError(sender, args) {
            console.log(args.get_message());
        }

        return listItems;
    },

    commandButton1 = function () {

        var ctx = SP.ClientContext.get_current();
        var ItemIds = "";

        //get current list id
        var listId = SP.ListOperation.Selection.getSelectedList();

        //get all selected list items
        var selectedItems = SP.ListOperation.Selection.getSelectedItems(ctx);

        //collect selected item ids
        for (var i = 0; i < selectedItems.length; i++) {
            ItemIds += selectedItems[i].id + ",";
        }

        //prepare the application page that gets the selected item ids passed in query string
        var pageUrl = SP.Utilities.Utility.getLayoutsPageUrl(
            '/Ribbon.Examples/ProcessCommand.aspx?ids=' + ItemIds + '&listid=' + listId);
        var options = SP.UI.$create_DialogOptions();
        options.autosize = true;
        options.url = pageUrl;
        options.dialogReturnValueCallback = Function.createDelegate(null, OnDialogClose);
        SP.UI.ModalDialog.showModalDialog(options);
    }

    //called on dialog closed
    OnDialogClose = function (result, target) {
        //if ok button is clicked in dialog, reload the grid.
        SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
    },

    commandButton2 = function () {
        alert('Not implemented');
    },

    commandButton3 = function () {
        alert('Not implemented');
    }


    //public interface
    return {
        eButton1: enabledButton1,
        eButton2: enabledButton2,
        eButton3: enabledButton3,
        cButton1: commandButton1,
        cButton2: commandButton2,
        cButton3: commandButton3,
    }

}();

The Application Page

This is quite a basic application page. It is important to notice that the context of the command can be identified (the SharePoint web site from the SPContext, the list id and the ids of the selected items from the query string).

application-page-page-load

The full SharePoint solution (source code) can be downloaded from here – Ribbon.Examples.

Tags: , , , ,

Trackback from your site.

Denis Stadler

I'm a technology enthusiast, with more than 10 years of experience in SharePoint and Dynamics CRM projects. To find more details about, please visit the about me page.

Leave a comment

*