Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 859
  • Last Modified:

Custom Ribbon Action - Disabled with Document Set Selection

The custom action enables/disables when a list item or folder is selected/deselected. The issue I'm running into is when a document set is selected, the custom action remains disabled.


Custom Ribbon Action:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
      Id="LinkDocsCustom"
      Location="CommandUI.Ribbon"
      RegistrationType="ContentType"
      RegistrationId="0x01">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
          <Group
              Id="LinkDocsCustomGroup"
              Sequence="15"
              Description="Copy permanent link to clipboard"
              Title="Permanent Link"
              Template="LinkDocsCustomGroupTemplate">
            <Controls Id="LinkDocsCustomGroupControl">
              <Button
                  Id="LinkDocsCustomGroupControlButton"
                  Sequence="5"
                  Command="SimpleAlert"
                  Image32by32="/_layouts/1033/images/formatmap32x32.png" Image32by32Left="-448" Image32by32Top="-128"
                  Description="Copies a permanent link to the clipboard"
                  LabelText="Copy Link to Clipboard"
                  ToolTipTitle="Copy Link to Clipboard"
                  TemplateAlias="o1" />
            </Controls>
          </Group>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Templates._children">
          <GroupTemplate Id="LinkDocsCustomGroupTemplate">
            <Layout Title="LargeLarge">
              <OverflowSection Type="OneRow" TemplateAlias="o1" DisplayMode="Large"/>
              <OverflowSection Type="OneRow" TemplateAlias="o2" DisplayMode="Large"/>
            </Layout>
          </GroupTemplate>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Documents.Scaling._children">
          <MaxSize Id="Ribbon.Documents.Scaling.Custom.MaxSize" Sequence="15" GroupId="LinkDocsCustomGroup" Size="LargeLarge" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
          Command="SimpleAlert"
          CommandAction="javascript:CopyLinkToClipboard();"
          EnabledScript="javascript:EnableCopyLinkToClipboard();"/>
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>

  <CustomAction
     Id="CopyLinkToClipboardScript"
     Location="ScriptLink"
     ScriptSrc ="/_layouts/15/CustomMenuAction/CopyLinkToClipboard.js"/>
</Elements>

Open in new window


JavaScript:

// This method contains the code needed to request the unique url to the document
function CopyLinkToClipboard() {
    // First get the context and web
    var ctx = SP.ClientContext.get_current();
    this.web = ctx.get_web();
    // Get the current selected list, then load the list using the getById method of Web (SPWeb)
    var listId = SP.ListOperation.Selection.getSelectedList();
    var sdlist = this.web.get_lists().getById(listId);
    // Get the currently selected item of the list. This will return a dicustonary with an id field
    var items = SP.ListOperation.Selection.getSelectedItems(ctx);
    var mijnid = items[0];
    // Request the list item from the server using the getItemById method. This will load all properties.   
    // If needed, one could pre-request the fields to be loaded to preserve bandwidth.
    this.listItem = sdlist.getItemById(mijnid.id);
    // load the item in the context for batch operation.
    ctx.load(this.listItem);
    //Execute the actual script on the server side. Specify delegates to handle the response. 
    ctx.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

// Delegate that is called when server operation is complete upon success.
function onQuerySucceeded(sender, args) {
    // Request url by using the get_item method. It will return the Url field type, which has a Url property. 
    var url = this.listItem.get_item('_dlc_DocIdUrl').get_url();
    // Request the name of the document. 
    var title = this.listItem.get_item('FileLeafRef');
    // Copy Link To Clipboard (Only works in Internet Explorer)
    window.clipboardData.setData('Text', url);
    // Notify the user that the link was successfully copied
    var notificationId = SP.UI.Notify.addNotification('Link Successfully Copied to Clipboard');
}

// Delegate that is called when server operation is completed with errors.
function onQueryFailed(sender, args) {
    alert('failed ' + args.toString());
}

// Method to enable/disable the button on the ribbon or ECB. 
function EnableCopyLinkToClipboard() {
    var enable = true;
    var context = SP.ClientContext.get_current();
    var selection = SP.ListOperation.Selection.getSelectedItems(context);

    // Check if more than one item is selected, disable the button if items > 1
    if (CountDictionary(selection) == 1)
        this.enable = true;
    else
        return false;
    // Check if a folder is selected
    var item;
    for (item in selection) {
        if (selection[item].fsObjType != 0)
            enable = false;
    }
    return enable;
}

Open in new window

0
brendanlefavre
Asked:
brendanlefavre
  • 7
  • 6
1 Solution
 
brendanlefavreAuthor Commented:
I'm trying this, but get an error when it tries to load the content type

function EnableCopyLinkToClipboard() {
    var enable = true;
    var context = SP.ClientContext.get_current();
    var selection = SP.ListOperation.Selection.getSelectedItems(context);

    // Check if more than one item is selected, disable the button if items > 1
    if (CountDictionary(selection) == 1)
        this.enable = true;
    else
        return false;
    // Check if a folder is selected
    var item;
	var _contentType = item.get_contentType();
    for (item in selection) {
	    alert(_contentType);
        if (selection[item]._contentType != 'Document')
            enable = false;
    }
    return enable;
}

Open in new window

0
 
Jamie McAllister MVPArchitectCommented:
Did you get 'PropertyOrFieldNotInitializedException' or something else?

Line 13?
0
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 
brendanlefavreAuthor Commented:
I'm getting "Object doesn't support property or method 'get_contentType'" on line 13
0
 
Jamie McAllister MVPArchitectCommented:
// Check if a folder is selected
    var item;
	var _contentType = item.get_contentType();

Open in new window


Looking at the above code, Item gets declared but never initialized to any type of object?
0
 
brendanlefavreAuthor Commented:
what do I need to do to get the object initialized?
0
 
Jamie McAllister MVPArchitectCommented:
Check out the sample from the link I sent (shown below).

After getting the selected item, the actual list item instance is obtained; this.listItem =  list.getItemById(items[k].id);

Then in the Product received function it looks like your code except the Var is initialized as so;
var item = this.listItem;
              var _contentType =  item.get_contentType();



var listItem;
function someFunction()
{
var ctx = SP.ClientContext.get_current();            
            items = SP.ListOperation.Selection.getSelectedItems(ctx);
for (k in items)
            {
              this.listItem =  list.getItemById(items[k].id);
              ctx.load(this.listItem,'Title', 'ContentType');
              ctx.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));

            }
}


 function productReceived() {
              var item = this.listItem;
              var _contentType =  item.get_contentType();
              if(_contentType.get_name() == 'Document Set')
              {
                 alert('Document Set Item is selected')                 
              }
            }

function failed(sender, args) {
                alert('failed. Message:' + args.get_message());
            }

Open in new window

0
 
brendanlefavreAuthor Commented:
I have tried your suggestion, and get the following error

script error

this is how i'm calling the custom script
get content type action
0
 
Jamie McAllister MVPArchitectCommented:
Please post your latest script here.
0
 
brendanlefavreAuthor Commented:
var listItem;
function someFunction() {
    var ctx = SP.ClientContext.get_current();
    items = SP.ListOperation.Selection.getSelectedItems(ctx);
    for (k in items) {
        this.listItem = list.getItemById(items[k].id);
        ctx.load(this.listItem, 'Title', 'ContentType');
        ctx.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));
    }
}

function productReceived() {
    var item = this.listItem;
    var _contentType = item.get_contentType();
    if (_contentType.get_name() == 'Document Set') {
        alert('Document Set Item is selected')
    }
}

function failed(sender, args) {
    alert('failed. Message:' + args.get_message());
}

Open in new window

0
 
Jamie McAllister MVPArchitectCommented:
It looks OK to me.

I'd put some diagnostics after var item = this.listItem; to ensure you really have a List Item at that point. Put some Alerts in there to examine the item title or whether it's null. That will narrow down the investigation as to whether there's an item or .get_contentType() is the problem.
0
 
brendanlefavreAuthor Commented:
I got this work, and will post the final code
0
 
Jamie McAllister MVPArchitectCommented:
Good work!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now