2

I am working on an app for SharePoint 2013.

I want to add a custom action to a context menu of a document library. And I want to call a JavaScript function with a selected item id and list id as parameters. A JavaScript function is placed in the app.js file. I am using Visual Studio 2012 to add the custom action for the menu.

UrlAction Url="javascript:getItemDetails({ItemId},{ListId})"

I tried to call the JavaScript function using URLAction in the element.xml file as I use to do it in SharePoint 2010. But I am getting the below error.

Error occurred in deployment step 'Install app for SharePoint': There were errors when validating the App Package.

And then I placed a simple JavaScript alert. That also not worked, and I got the same error.

If anybody knows the fix, please help me.

  • Did anything come out of this? I'm running into the same issue and cannot find any great answers out there. This definitely seems like it should be possible... – mwilson Aug 6 '14 at 23:57
  • I had the same issue on SharePoint Online, you should us some other attributes, please follow this link: codeproject.com/Articles/754808/… – user35159 Nov 13 '14 at 20:26
3

According to MSDN that is not possible:

CustomAction cannot contain JavaScript: Any UrlActions or CommandActions must be a URL to navigate to. The URL can be parameterized with normal custom actions tokens in addition to the app-specific tokens.

Also in ULS:

Custom action urls must start with "http:", "https:", "~appWebUrl" or "~remoteAppUrl".

You might want to try using HostWebDialog="TRUE" and reference a page from Application Web.

  • 1
    The MSDN documentation is actually wrong. You can write JS in the URL attribute as long as you include the full code in the attribute, namely include the function definition in the attribute before the function call. Defining the function somewhere else outside the attribute will not work. Also, you can write an IIFE (Immediately Invoked Function Expression) to make the code shorter. See example here. – Mihail-Florin Popa Jan 6 '16 at 12:30
  • Now that I have a reputation score allowing me to comment, let me direct the reader to see my answer below from Feb 8 '16 at 17:35. The MSDN documentation is not wrong. The example given is for SharePoint 2010 development and is not pertinent to 2013 add-in development. JavaScript is not allowed in Custom Action urls. – flayman Jun 14 '17 at 11:18
1

Edit: It would be nice and much appreciated if someone would like to upvote this answer and/or mark it as a solution. There is a lot of misinformation out there as to what is allowed in SharePoint Add-in development. This is how you create custom actions that execute JavaScript. Other ways do not work.

Mihail Popa is incorrect in his comment from Jan 6 2016 at 12:30. The MSDN documentation is not wrong. The question pertains to SharePoint 2013 app development. The example linked to in the comment is for SharePoint 2010 solution development. "SharePoint > SharePoint 2010 - Development and Programming" - it couldn't be clearer. In SP 2013 app development (now called add-in development), javascript is not allowed in the XML for custom actions. It is unfortunate that there is so much confusion in the MS developer community about what is allowed in custom actions in SharePoint 2013. Trying to be helpful, many have offered answers but given examples for SharePoint 2010. The solutions offered are not relevant to SharePoint 2013 add-in development and such answers are only adding to the confusion. They do not even build in SharePoint Add-in Visual Studio projects.

There is a way to make this work though, using an AppEventReceiver. I have provided an answer to another StackExchange question. Here it is again:

I used this article as a guide: https://lixuan0125.wordpress.com/2014/03/04/add-custom-action-through-csom-with-app/ (credit goes to the author, lixuan0125)

You need to add the custom action in the App Installed event handler with client side code. Some others have alluded to this technique without enough detail to be getting on with. The article gives an example of a static method, which is apparently meant to be called from the event receiver that is created when you set "Handle Add-in Installed" to True in the project properties for the Add-in project. I simplified the approach and my AppEventReceiver class looks a bit like this:

public class AppEventReceiver : IRemoteEventService
{
    public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
    {
        SPRemoteEventResult result = new SPRemoteEventResult();

        switch (properties.EventType)
        {
            case SPRemoteEventType.AppInstalled:
                HandleAppInstalled(properties);
                break;
        }

        return result;
    }

    private void HandleAppInstalled(SPRemoteEventProperties properties)
    { 
        using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false))
        {
            if (clientContext != null)
            {
                try {
                    string title = "Example custom action";

                    clientContext.Load(clientContext.Web);
                    List list = clientContext.Web.Lists.GetByTitle("The title of your list"); // or use GetByID or whatever
                    UserCustomActionCollection collUCA = list.UserCustomActions;
                    clientContext.Load(list);
                    clientContext.Load(collUCA);
                    clientContext.ExecuteQuery();

                    bool found = false;
                    UserCustomAction newUCAToRemove = null;
                    for (int i = 0; i < collUCA.Count; i++)
                    {
                        if (collUCA[i].Title == title)
                        {
                            newUCAToRemove = collUCA[i];
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        newUCAToRemove.DeleteObject();
                    }

                    // Always replace existing custom action
                    UserCustomAction action = collUCA.Add();
                    action.Location = "CommandUI.Ribbon";
                    action.Sequence = 1000;
                    action.Title = title;
                    // Note: Location attribute can be any valid ribbon node with controls
                    action.CommandUIExtension = @"<CommandUIExtension><CommandUIDefinitions>"
                           + "<CommandUIDefinition Location=\"Ribbon.Documents.Manage.Controls._children\">"
                           + "<Button Id=\"InvokeAction.Button\" TemplateAlias=\"o1\" Command=\"Invoke_Command\" CommandType=\"General\" LabelText=\"Say hello to me\" Image32by32=\"_layouts/15/images/placeholder32x32.png\" Image16by16=\"_layouts/15/images/placeholder16x16.png\" />"
                           + "</CommandUIDefinition>"
                           + "</CommandUIDefinitions>"
                           + "<CommandUIHandlers>"
                           + "<CommandUIHandler Command =\"Invoke_Command\" CommandAction=\"javascript:alert('hi there');\" />"
                           + "</CommandUIHandlers></CommandUIExtension>";

                    action.Update();

                    clientContext.ExecuteQuery();
                } catch(Exception ex)
                {
                    throw new System.Net.WebException("Error when handling App Installed event.", ex);
                }
            }
        }
    }
}

You need to make sure that you give the Add-in sufficient permission to set custom actions on the list. This gave me some grief for a while. "Allow the add-in to make app-only calls to SharePoint." is essential in the AppManifest. It will work if you give FullControl permission for the Web scope and the installing user is able to grant it. I don't know yet whether anything lower or more granular will work.

0

You must be missing something, or done some changes to your package which invalidates it. SharePoint 2013 does support Custom Actions in Ribbon and ECB, even in SharePoint Apps.

This example gives a full working example http://msdn.microsoft.com/en-us/library/bbd11f94-1798-453e-bbb0-e5eb0df8dc75. The major difference is how you use Tokens to address the Host Web or Client Web. Here is an excerpt from the article showing the exact definition of the Custom action Elements.xml

<?xml version="1.0" encoding="utf-8"?>
<Elements 
    xmlns="http://schemas.microsoft.com/sharepoint/">
    <!-- RegistrationId attribute is the list type id,
        in this case, a document library (id=101). -->
  <CustomAction 
      Id="65695319-4784-478e-8dcd-4e541cb1d682.CustomAction"
      RegistrationType="List"
      RegistrationId="101"
      Location="EditControlBlock"
      Sequence="10001"
      Title="Invoke custom action">
    <!-- 
    Update the Url below to the page you want the custom action to use.
    Start the URL with the token ~remoteAppUrl if the page is in the
    associated web project, use ~appWebUrl if page is in the app project.
    -->
    <UrlAction Url=
"~remoteAppUrl/CustomActionTarget.aspx?HostUrl={HostUrl}&amp;Source={Source}&amp;ListURLDir={ListUrlDir}&amp;ListID={ListId}&amp;ItemURL={ItemUrl}&amp;ItemID={ItemId}" />
  </CustomAction>
</Elements>
  • Hi Marius, Thank you for ur response.I followed the same example.But in this example when this url action will redirect the user to another page.But i don't want the user to redirected to another page.Instead i want to call a javascript function to update another one list.I have done the same in sharepoint 2010.It works fine.But here only it's giving error.I want to fix this issue. – user10000 Feb 19 '13 at 5:52
  • the main issue you are facing is that the app model is functioning differently and updating a list might mean crossing site collections boundaries. have you considered using the cross-domain libraries (msdn.microsoft.com/en-us/library/fp179927.aspx)? – Marius Constantinescu - MVP Feb 19 '13 at 9:50
  • 1
    i want to call a javascript function(resides in App.js) in the url action.how to do it? – user10000 Mar 4 '13 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.