Tuesday, October 17, 2017

Putting an button on each line item & updating list with calculated column

Recently I was working on a feature which required me to put a button on every item in the SharePoint list's view. The button name was Assign Me. When clicked, it should update the item and put the current logged in user in the Assigned To field.




I followed a hybrid approach. calculated column and custom JavaScript. I tried doing everything in calculated column. Even though calculated columns allow writing code in JavaScript, they still have some limitations. One of the biggest hurdle is to get the ID of the item. Since calculated columns do not allow ID column, you have to be innovative. I figured out that the checkbox column in every line item has id in the
tag. This is always the first column in the view (first td in the tr).

Following are the steps I followed to achieve the desired result. 

Step 1. Create a new calculated column with output as Number. 
Step 2. Put the following formula. I use Typescript, hence replace class name with your's in the below formula. 



Step 3. Add a script editor to your page and link your .js file.
Step 4. In the Typescript file, following are the two functions.
     initAssignMe(trObj) {
        var oSelf = YourClassName;
        try {
            console.log(trObj.childNodes[0].childNodes[0].title); //This gives you ID
            var itemID = trObj.childNodes[0].childNodes[0].title;
            if (confirm('Do you want to assign the current task to yourself?')) {
                //I am using some fancy stuff to block the entire UI while I update the item.
                $.blockUI({ 
                    css: {
                        padding: '5px 0 5px 0',
                        margin: 0,
                        width: '20%',
                        top: '40%',
                        left: '40%',
                        textAlign: 'center',
                        color: '#000',
                        border: '3px solid #aaa',
                        backgroundColor: '#fff',
                        cursor: 'wait'
                    },
                    message: "Assigning Task",
                    fadeIn: 1000,
                    timeout: 3000,
                    onBlock: function () {
                        oSelf.prototype.updateTask(itemID);
                    }
                });                
            }
        } catch (e) { YourUtilClass.Log(window.location.href.substr(0, 254), "YourClassName - initAssignMe", e.message, e.stack); }
    }

    updateTask(itemID) {
        try {
            var ctx = SP.ClientContext.get_current();
            var oWeb = ctx.get_web();
            var SWTList = oWeb.get_lists().getByTitle('YOUR TASK LIST');
            var oListItem = SWTList.getItemById(itemID);

            oListItem.set_item('Task_x0020_Owner', _spPageContextInfo.userId);
            oListItem.update();
            ctx.load(oListItem);
            ctx.executeQueryAsync(function () {
                alert('Task assigned successfully!');
                window.location.reload();
            },
                function (sender, args) {
                    YourUtilClass.Log(window.location.href.substr(0, 254), "YourClassName updateTask (CSOM)", args.get_message(), args.get_stackTrace());
                    alert('Something went wrong!');
                }
            );
        } catch (e) { YourUtilClass.Log(window.location.href.substr(0, 254), "YourClassName updateTask", e.message, e.stack); }
    }



Once done, you should see a button 'Assign Me' in every line item. 

Hope this helps!

-Vighnesh

Wednesday, June 8, 2016

Migrating Lists with Lookup Fields

One of the basic activity while working on SharePoint site is to migrate lists/libraries from one site to another. If you have a lookup field in the list then the task is not basic anymore. 

I faced this issue several times. I never gave it a thought and always used to recreate the list at destination site. But recently I stumbled upon a blog from Maulik Dhorajia who has described this issue in detail. 

In my case, I was moving 3 lists & 1 document library. This 1 doc lib had reference (lookup column) to other 3 lists. All the steps were same except I had to add all document in the VS 2013 project along with the manifest.xml file.

Below are the steps in brief...

  1. Create list templates with content,
  2. Create parent lists in destination site,
  3. Note down list GUID for the newly created list,
  4. Rename doc lib the stp file to .cab,
  5. Extract the manifest.xml file,
  6. Look for the old list id and replace it with new list id,
  7. Create a new project in VS - CAB Project. I had to download the template from Microsoft site,
  8. Add all the documents along with manifest.xml file to the project. If you are migrating a list, then you will only have manifest.xml file,
  9. Build the project, go to debug\bin folder,
  10. Find the .cab file and rename it to .stp,
  11. Upload the template to the gallery & create a list/library out of it,
  12. That's It.
Its a bit of workaround, but if you have a large list then this is your saviour.