Saturday, 22 November 2014

SharePoint 2013/Online: Get current logged in user's groups using javascript

This Post explains how to get current logged in users Groups using javascript. Its a simple ajax call to the sharepoint service. Use the below code

$(document).ready(function () {
     var userid = _spPageContextInfo.userId;
getCurrentUserGroups(userid);
});
function getCurrentUserGroups(UserID) {
    $.ajax({
        url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/GetUserById(" + UserID + ")/Groups",
        type: "GET",
        headers: { "Accept": "application/json; odata=verbose", "X-RequestDigest": $("#__REQUESTDIGEST").val() },
        dataType: "json",
        async: true,
        success: function (data) {
            /* get all group's title of current user. */
            var results = data.d.results;
            for (var i = 0; i < results.length; i++) {
               alert(results[i].Title);
            }
        }
    });
}

How to hide a ribbon in SharePoint 2010/2013/Online using Jquery

This post explains how to hide a SharePoint Ribbon in SP 2010/2013/ SP Online using jquery.
It is very simple jquery code to hide the ribbon.
For example say suppose you want to hide Add New Item Ribbon in a List called Contacts.
Here is how efficiently we can achieve this.

$(document).ready(function () {
    var currentPage = decodeURIComponent(window.location.href.replace(/\+/g, " "));
    if (currentPage.contains("Lists/Contacts")) {
      window.setTimeout(hideRibbon, 500);
    }
});
function hideRibbon() {
    $('span[id^="Ribbon.ListItem.New.NewListItem"]').hide()
    window.setTimeout(hideRibbon, 200);
}
Above simple jquery code does the trick. As you can see, if the url is lists/contacts, we are calling the method  hideRibbon with a delay. And in the hideRibbon method we are calling the same method again with a delay. which will keep hiding the ribbon.

Happy coding :)

SharePoint: Save string content as a file in Document Library from Client Side with a metadata column.

My previous post Save string content as a file in Document Library from Client Side explains how to add a string content as a file in SharePoint document Library.
This post just extends the previous post. Suppose you have a metadata column in document library which describes some metadata about the file.
For example there is a column called "FileInfo" which will describe some information about the file. So now we need to pass value to this column while adding the file.
Let us see how this can be done.
function AddFileToDocumentLibrary(str) {
    var strm = Base64.encode(str);
    strm = strm.replace(/ /g, '');
    $().SPServices({
        operation: "CopyIntoItems",
        webURL: getCurrentUrl(),
        processData: false,
        async: false,
        SourceUrl: "http://null",
        Stream: strm,
        Fields: "<FieldInformation Type='Text' DisplayName='FileInfo' InternalName='FileInfo'  Value='This File Contains Contact Information' />",
        DestinationUrls: [getCurrentUrl() + "DocumentLibraryName/Contact.txt"],
        completefunc: function (xData, Status) {
             alert("Status=" + Status);
         
        }
    });
}
function getCurrentUrl() {
    var thisSite = $().SPServices.SPGetCurrentSite(); //if this line of code doesn't give you the url, try commenting this line and uncommenting the below line.
    //var thisSite = _spPageContextInfo.siteAbsoluteUrl;
    return thisSite + "/";
}
In the above code as you can see the option Fields allows us to provide values to the columns in the List/Library.
Please don't forget to incluse SPServices js file ans jquery.Base64.min.js (create a js file with this name and copy js code from here how-to-encode-and-decode-strings-with-base64-in-javasript) file.
Happy coding :)

Wednesday, 19 November 2014

SharePoint 2013: setting People Picker Value in NewForm.aspx

SharePoint 2013, people picker supports auto complete. You will not see the address book and the resolve user button any more on the new form.aspx.  If you are looking for a short cut key to resolve the user you can still use Cntrl + K  key combination.

SharePoint 2013 people picker.
In order to provide support for people picker in apps, Microsoft has come up with three new files as given below and is located in the 15 hive.
  1. clientform.js
  2. clientpeoplepicker.js
  3. autofill.js
The above 3 files contains most of the functionality required to be performed by people picker.
Here is the code to fill a people picker in SP2013 with a User.
function SetAndResolvePeoplePicker(fieldName, userAccountName) {
    var controlName = fieldName;
    var peoplePickerDiv = $("[id$='ClientPeoplePicker'][title='" + controlName + "']");
    var peoplePickerEditor = peoplePickerDiv.find("[title='" + controlName + "']");
    var spPeoplePicker = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDiv[0].id];
    peoplePickerEditor.val(userAccountName);
    spPeoplePicker.AddUnresolvedUserFromEditor(true);           
     //disable the field

     spPeoplePicker.SetEnabledState(false);

        //hide the delete/remove use image from the people picker

        $('.sp-peoplepicker-delImage').css('display', 'none');

   }
In the above method, the parameters:
fieldName: Name of the people picker column
userAccountName: user name (ex: domain\username).

Hope this Posts helps. Please comment below if you have better solution.

The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist. Use Ribbon.MakeTabAvailable()

"The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist. Use Ribbon.MakeTabAvailable()"


Have you come acrossthis error on your page?
Then don't worry. its not your fault but a riddle left by MSFT. 
I know that you got this error when playing with wiki pages. Yes, if wiki pages are rendered in IFrame (SPModalDialogue) or wiki page url has IsDlg=1(as part of querystring) this error shows up in sharepoint logs. 
Solution:
You can simply fix this by changing the type of the page from wiki to webpart page. 


Sunday, 9 November 2014

SharePoint Get Current Web URL

How to get SharePoint site current URL ?

We can get SharePoint Current web url in Server-Side as well as in Client side.

Server Side:

 As we all know current web url can be accessed in server side by web object as below.

SPContext.Current.Web.Url

Client Side:

In client side , we can achieve this by using SPServices .

Here is how to achieve this:
Include SPServices js file in your page.
Now you can access the url this way:
var thisWebUrl = $().SPServices.SPGetCurrentSite();
But there is a bug in recent versions of SPServices , where the above method will return only "/".
But in SharePoint 2013, we  can access web url as below as well :
var thisWebUrl = _spPageContextInfo.webAbsoluteUrl; (web url)
var thisSiteUrl = _spPageContextInfo.siteAbsoluteUrl; (site url)
Enjoy coding :)

SharePoint: Save string content as a file in Document Library from Client Side.

This Post explains you how to Save a string content as a file in SharePoint Document Library.
Refer this Post if you want to pass value to a column as well SharePoint: Save string content as a file in Document Library from Client Side with a metadata column
Use the below javascript code: (include SPService reference.)

function AddFileToDocumentLibrary(str) {
    var strm = Base64.encode(str);
    strm = strm.replace(/ /g, '');
    $().SPServices({
        operation: "CopyIntoItems",
        webURL: getCurrentUrl(),
        processData: false,
        async: false,
        SourceUrl: "http://null",
        Stream: strm,
        DestinationUrls: [getCurrentUrl() + "DocumentLibraryName/file.txt"],
        completefunc: function (xData, Status) {
             alert("Status=" + Status);
         
        }
    });
}
function getCurrentUrl() {
    var thisSite = $().SPServices.SPGetCurrentSite(); //if this line of code doesn't give you the url, try commenting this line and uncommenting the below line.
    //var thisSite = _spPageContextInfo.siteAbsoluteUrl;
    return thisSite + "/";
}
Please don't forget to incluse SPServices js file ans jquery.Base64.min.js (create a js file with this name and copy js code from here how-to-encode-and-decode-strings-with-base64-in-javasript) file.

Happy coding :)

Thursday, 26 June 2014

spFile.OpenBinary() error : file could not be opened

Are you facing this problem while opening the spfile using the url..?
SPFile spFile = web.GetFile("/Document Library Name/" + FileName+ ".jpg");
byte[] binFile = spFile.OpenBinary();  <----- error that file could not be opened
Here is the solution.
Get the SPListItem that contains your file.
Use CAML Query to get the list item by passing the column name and its value.
    SPList list= web.Lists["Document Library Name"];
    SPQuery query = new SPQuery();
    query.Query = "<Where><Eq><FieldRef Name=\"" + columnName + "\"/><Value Type=\"Text\">" + value + "</Value></Eq></Where>";
    SPListItemCollection itmColl = SPListItemCollection itmcol = list.GetItems(query);
    SPFile picture=null;
    if (itmcol.Count > 0)
     {
        picture = itmcol[0].File;
        //byte[] binFile = spFile.OpenBinary();
     }
     byte[] fileData = picture.OpenBinary();

Wednesday, 25 June 2014

Creating SharePoint State Machine Workflow

State machine workflow is the powerful feature of SharePoint, which can be easily done using Visual Studio.
click here to read my previous tutorial for Creating a SharePoint Sequential Visual Studio Workflow (2 or n Level) 
click here to read my previous tutorial on Creating a SharePoint Sequential Visual Studio Workflow (1 Level) 
Let me explain how to create a state machine workflow with a example scenario.
Scenario:
Let's consider a scenario in college.
  • When a student requests for some document with the Administration office, first it goes to an officer, when he approves, it goes to higher officer for approval.
  • When first officer approves, it has to go to next officer and when the 2nd officer approves, the workflow is complete.
  • When first officer rejects, it has to go back to student for re-submission.
  • When first officer approves, and second officer rejects, it has to go back to the first officer for re-approval.
Let us create a state machine workflow that matches above scenario. Let's go through step by step.
1.Open Visual studio (Run as administrator).
 Select State Machine Workflow under SharePoint 2010 template. Enter the project name

2. Enter your site address and select farm solution and click next

3. Select List workflow and click next
  
4. Select the list , in our case Shared Documents.

5. A workflow can be started (triggered) in 3 ways:
    a) Manually
    b) When item is created
    c) When item is updated
Select 'when an item created' and click finish

6. Now you can see the screen as below with your workflow design and toolbox at left side.

7. Use the toolbox and drag and drop 2 State Activities to your workflow design, so your final design will look as below.

  8. Select the Workflow1InitialState and press F4 to open its properties. Rename this to InitialState as shown below

9. Similarly rename the other 2 stateActivities to stateApproval and stateComplete.

10. Right click on InitialState and select Set as Initial State
  
11. Right click stateComplete   and select Set as Completed State
 12. Double click on EventDrivenActivity1 in Initial state. Below screen would appear.

13. Drag and drop SetState Activity below onWorkflowActivated1


14. Select setStateActivity1 press F4, in the properties panel set stateApproval as TargetStateName

15.  Click on Workflow1 to go back to the main design window.

16. Now your design would look like this

17. Right click on stateApproval, select Add StateInitialization

18.  Below screen would appear,

19. Drag and drop Create Task from the toolbox

20. Select CreateTask1, press F4, in the properties window type Correlation token as task token and OwnerActivityName as stateApproval.

 21. Click TaskId, click on the small bubble that appears at the end or double click on small yellow box. Below screen would appear and select "Bind to a new member" and hit "Create Field". click OK

22. Repeat the above process for TaskProperties.

23 . Now right click on stateApproval and select Add EventDriven




24. Now below the eventdriveActivity drag and drop OnTaskChanged, 2 IfElse (one inside another), and 3 SetState activities and make your design look like below.

25. select setStateActivity2 , press F4, and Choose the TargetStateName as stetComplete.

26. Repeat the above process for setStateActivity3 and setStateActivity4 by giving TargetStateName as stateApproval. Now the design will look like below.

27. select OntaskChanged1 and press F4, in the properties panel, double click on the small bubble appearing at the end of textbox for AfterProperties and choose Bind to a new member, select create field.

 28. repeat above step for BeforeProperties as well.
 29. select correlation token as task token, Click the bubble near Taskd and select Bind to existing member, select CreateTask1_TaskId1, click OK.

30. Now we are done with the design part and go back to  main design window, your design should look like this.

31. In the InitialState, double click on EventDrivenActivity1 and now double click on onWorkflowActivated1:
        List<string> approverList = new List<string>();
        int currentLevel;
        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
        {
            //you can read approvers from sharepoint list as well and save to approverList
            approverList.Add(@"domain\user1");
            approverList.Add(@"
domain\user2");

            currentLevel = 1;
        }
add these 2 lines above the method
List<string> approverList = new List<string>();
        int currentLevel;
32. Now go back to main design window, double click on stateInitializationActivity1 under stateApproval and now double click on createTask1. and enter below code.
       private void createTask1_MethodInvoking(object sender, EventArgs e)
        {
            createTask1_TaskId1 = Guid.NewGuid();
            if (currentLevel == 0)
            {
                string user = workflowProperties.Item["Author"].ToString();
                if (user.Contains("#"))
                {
                    user = user.Substring(user.IndexOf("#"));
                }
                SPUser user1 = workflowProperties.Web.EnsureUser(user);
                createTask1_TaskProperties1.AssignedTo = user1.LoginName;
            }
            else
            {
                SPUser user = workflowProperties.Web.EnsureUser(approverList[currentLevel - 1]);
                createTask1_TaskProperties1.AssignedTo = user.LoginName;
            }
            createTask1_TaskProperties1.Title = "please Approve";
        }

33. Now go back to main design and double click on eventDrivenActivity2 and now double click on onTaskChanged1, enter the below code.
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
        {
            onTaskChanged1_AfterProperties1 = onTaskChanged1.AfterProperties;
            onTaskChanged1_BeforeProperties1 = onTaskChanged1.BeforeProperties;
        }
34. Now copy below 2 methods
     private void isApproved(object sender, ConditionalEventArgs e)
        {
            if (onTaskChanged1_AfterProperties1.PercentComplete == 1.0)
            {
                currentLevel++;
                e.Result = true;
            }
            else
            {
                if (currentLevel == 1)
                {
                    //assign to requestor
                    currentLevel = 0;
                                  e.Result = false;
                }
                else
                    if (currentLevel > 1)
                    {
                        currentLevel--;
                        e.Result = false;

                    }
            }
        }

        private void isApprovalSequenceComplete(object sender, ConditionalEventArgs e)
        {
            if (currentLevel > approverList.Count)
            {
                //Approval complete
                e.Result = true;
            }
            else
            {
                //goto to next approver
                e.Result = false;
            }
        }
 35. Now select IfElseBranchActivity1, press F4, in the properties panel, choose CodeCondition for Condition, and select isApproved method for condition.

36. Repeat above procedure for IfElseBranchActivity3 and select codition as isApprovalSequenceComplete
37. Now we are done with the code, build the solution, and then deploy

38. Go to Shared Documents and upload some document

39. Now you can see your workflow showing in a new column with status as InProgress Since we have selected workflow to begin "when an item created"


40. Click on InProgress and it will open the WorkFlow properties. Edit the created task as shown.
  
41. Enter 100 for %Complete field and Save

42.  As you can see, the task has been created for the next approver.

43.  Edit it as we have done previously, make the %complete to 100 and save.
Now go back to the list. As you can see the workflow is Completed.
 You can check this for our scenario where,
  1. If 1st person approves, goes to 2nd person, 2nd person approves, workflow complete
  2. 1st person rejects, task goes to document requestor
  3. 2nd person rejects task assigns to 1st person
  Below is the complete code for reference:
namespace StateMWF.Workflow1
{
    public sealed partial class Workflow1 : StateMachineWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
        public Guid createTask1_TaskId1 = default(System.Guid);
        public SPWorkflowTaskProperties createTask1_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChanged1_AfterProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChanged1_BeforeProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

        List<string> approverList = new List<string>();
        int currentLevel;
        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
        {
            //you can read approvers from sharepoint list as well and save to approverList
            approverList.Add(@"domain\user");
            approverList.Add(@"domain\user");

            currentLevel = 1;
        }

        private void createTask1_MethodInvoking(object sender, EventArgs e)
        {
            createTask1_TaskId1 = Guid.NewGuid();
            if (currentLevel == 0)
            {
                string user = workflowProperties.Item["Author"].ToString();
                if (user.Contains("#"))
                {
                    user = user.Substring(user.IndexOf("#"));
                }
                SPUser user1 = workflowProperties.Web.EnsureUser(user);
                createTask1_TaskProperties1.AssignedTo = user1.LoginName;
            }
            else
            {
                SPUser user = workflowProperties.Web.EnsureUser(approverList[currentLevel - 1]);
                createTask1_TaskProperties1.AssignedTo = user.LoginName;
            }
            createTask1_TaskProperties1.Title = "please Approve";
        }

        private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
        {
            onTaskChanged1_AfterProperties1 = onTaskChanged1.AfterProperties;
            onTaskChanged1_BeforeProperties1 = onTaskChanged1.BeforeProperties;
        }
        private void isApproved(object sender, ConditionalEventArgs e)
        {
            if (onTaskChanged1_AfterProperties1.PercentComplete == 1.0)
            {
                currentLevel++;
                e.Result = true;
            }
            else
            {
                if (currentLevel == 1)
                {
                    //assign to requestor
                    currentLevel = 0;
                              e.Result = false;
                }
                else
                    if (currentLevel > 1)
                    {
                        currentLevel--;
                        e.Result = false;

                    }
            }
        }
        private void isApprovalSequenceComplete(object sender, ConditionalEventArgs e)
        {
            if (currentLevel > approverList.Count)
            {
                //Approval complete
                e.Result = true;
            }
            else
            {
                //goto to next approver
                e.Result = false;
            }
        }
    }
}
Explanation:
  • When an item in Shared Document is created, the workflow is triggered.
  • Initially when workflow is activated, we are getting data for list of approvers. Here you can modify the code to get the approvers from sharepoint list as well.
  •  Task is created for the first approver.
  • onTaskChanged will assign the task after properties and before properties to global variables.
  • Then using IfElse condition we will check if the currect task is approved, by checking the percent complete. If complete we will move to the next approval level and create task for next approver. If not we will go back to previous level. (if task is rejected by 1st approver, it goes to the requestor, i.e. creates task for requestor).
  • It repeats until the approval sequence is complete.
happy coding :)