SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am working on App for sharepoint 2013. I want to add custom action to a context menu of a document library.And I want to call a javascript function with selected item id and list id as parameters.javascript function is placed in the app.js file. I am using VS 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 element.xml file as I use to do it in SP 2010.But I am getting 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.

share|improve this question
    
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/… – Octavian Nov 13 '14 at 20:26

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.

share|improve this answer
    
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 Popa Jan 6 at 12:30

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>
share|improve this answer
    
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

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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