Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Approve Workflow Tasks with SharePoint REST API

5.00/5 (2 votes)
29 Sep 2016CPOL2 min read 28.3K  
This article shows how to view the workflow status with Rest API, how to navigate to workflow approval page, how to approve and reject the task with SharePoint REST API

Approve Workflow Tasks and Navigate to Workflow Approval Page with SharePoint REST API

Many times, we have faced a situation where we need to approve / reject the workflow task or open the approval page of workflow task of any list item with SharePoint Rest API. This blog explains how to make Rest calls to show the workflow approval form or to directly approve or reject the workflow task.

Background Scenario

Let’s take a scenario of HR Request approval workflow.

Here, we are having an HR_Request list and ApprovalWorkflow associated with it. The task list associated with the workflow is HRTasks. Workflow will start automatically and assign task to HR Group when an item is added in the list.

First, let’s create a content editor webpart to show the status of the currently assigned task.

The following code shows how to create the webpart and the Rest API call for the same.

Using the Code

The webpart is made with Angular JS to show the status of the workflow task of the current item. The following code is used to show the design structure.

HTML
<style>
td{border: solid 1px black; padding: 5px;} 
th{border: solid 1px black; padding: 5px;}
</style>

<script type="text/javascript" src="/sites/jccademo/style library/pnp.min.js"></script>   
<script type="text/javascript" src="/sites/jccademo/style library/workflow.js"></script>
<table ng-app="mainapp" style="border:solid 1px black; background-color:white;">
    <thead ng-controller="getHRRequest">
        <tr>
            <th>Task Title</th>
            <th>Task Request</th>
            <th>Approval Status</th>
            <th>Link for Approve/Reject</th>
            <th>Approve</th>
            <th>Reject</th>
        </tr>
        <tr ng-repeat="item in items">
            <td>{{item.Title}}</td>
            <td>{{item.Request}}</td>
            <td>
                <div ng-if="item.Approval==16">Approved</div> 
                <div ng-if="item.Approval==15">Cancelled</div> 
                <div ng-if="item.Approval==17">Rejected</div> 
                <div ng-if="item.Approval==2">InProgress</div> 
                <div ng-if="item.Approval==5">Completed</div> 
                <div ng-if="item.Approval==0">NotStarted</div> 
            </td>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </thead>
</table>

Following is the Rest API call to find the status of the task.

JavaScript
var mainapp = angular.module("mainapp", []);
mainapp.controller('getHRRequest', ['$http', 'dataService', 
'$scope', function ($http, dataService, $scope) {
    var getHRRequest = _spPageContextInfo.webAbsoluteUrl + 
    "/_api/web/Lists/GetByTitle('HR_Request')/items?$select=ID,Title,
    Request,Approval&$orderby=Modified desc";

    $scope.items = [];
    dataService.get(getHRRequest).then(function (items) {
        $scope.items = items.data.d.results;

        angular.forEach(items.data.d.results, function (items) {
            var getCurrentUSerId = _spPageContextInfo.webAbsoluteUrl + 
            "/_api/Web/CurrentUser?$select=Id";

            dataService.get(getCurrentUSerId).then(function (users) {
                var getTaskId = _spPageContextInfo.webAbsoluteUrl+
                "/_api/lists/getbyTitle('HRTasks')/items?$select=Id,Title&$filter=WorkflowItemId eq " + 
                items.Id ;

                dataService.get(getTaskId).then(function (tasks) {
                    var Id = tasks.data.d.results.Id;
                });
            });
        })
    });
}]);

This will bind the details of the task status of each item of HR_Request list as shown below:

Rest Call to Get Associated Tasks from HRTasks List

Now, we need to make a rest call to get the tasks associated to current item from the HRTasks list. The Rest API endpoint is as follows:

/_api/lists/getbyTitle('HRTasks')/items?$select=Id,Title,AssignedToId&$filter=WorkflowItemId eq " + 
itemId 

where itemId is the Id of the HR_Request item and the WorkflowItemId is the Id of the item of associated list. This will show all the assigned tasks for the selected item.

Further, we can modify the rest call to get the assigned tasks to currently logged-in. REST call to get the logged-in user id is as below:

/_api/Web/CurrentUser?$select=Id

The modified Rest call for showing the link to approval page is shown below. Here, the link in HTML consists of the guid of the HR_Request list, i.e., cb305ecc-17af-4f08-9d16-5f96195fbe55.

HTML
<style>
td{border: solid 1px black; padding: 5px;} 
th{border: solid 1px black; padding: 5px;}
</style>

<script type="text/javascript" 
src="/sites/jccademo/style library/pnp.min.js"></script>   
<script type="text/javascript" 
src="/sites/jccademo/style library/workflow.js"></script>
<table ng-app="mainapp" 
style="border:solid 1px black; background-color:white;">
    <thead ng-controller="getHRRequest">
        <tr>
            <th>Task Title</th>
            <th>Task Request</th>
            <th>Approval Status</th>
            <th>Link for Approve/Reject</th>
            <th>Approve</th>
            <th>Reject</th>
        </tr>
        <tr ng-repeat="item in items">
            <td>{{item.Title}}</td>
            <td>{{item.Request}}</td>
            <td>
                <div ng-if="item.Approval==16">Approved</div> 
                <div ng-if="item.Approval==15">Cancelled</div> 
                <div ng-if="item.Approval==17">Rejected</div> 
                <div ng-if="item.Approval==2">InProgress</div> 
                <div ng-if="item.Approval==5">Completed</div> 
                <div ng-if="item.Approval==0">NotStarted</div> 
            </td>
            <td><a href="/sites/jccademo/_layouts/15/WrkTaskIP.aspx?
            List=cb305ecc-17af-4f08-9d16-5f96195fbe55&
            ID={{item.TaskId}}">Click</a></td>
            <td></td>
            <td></td>
        </tr>
    </thead>
</table>
JavaScript
var mainapp = angular.module("mainapp", []);
mainapp.controller('getHRRequest', ['$http', 
'dataService', '$scope', function ($http, dataService, $scope) {
    var getHRRequest = _spPageContextInfo.webAbsoluteUrl + 
    "/_api/web/Lists/GetByTitle('HR_Request')/items?$select=ID,
    Title,Request,Approval&$orderby=Modified desc";
    $scope.items = [];
    dataService.get(getHRRequest).then(function (items) {
        $scope.items = items.data.d.results;
        angular.forEach(items.data.d.results, function (items) {
            var getCurrentUSerId = _spPageContextInfo.webAbsoluteUrl + 
            "/_api/Web/CurrentUser?$select=Id";
            dataService.get(getCurrentUSerId).then(function (users) {
                var getTaskId = _spPageContextInfo.webAbsoluteUrl+
                "/_api/lists/getbyTitle('HRTasks')/
                items?$select=Id,Title&$filter=WorkflowItemId eq " + 
                items.Id +" and AssignedToId eq "+ users.data.d.Id;
                dataService.get(getTaskId).then(function (tasks) {
                    items.TaskId=tasks.data.d.results[0].Id;
                });
            });
        })
    });
}]);

Rest Call to Approve / Reject Items

Now, we need to update the tasks as either approved or rejected. To approve / reject the task, the function is as below.

JavaScript
$scope.ApproveTask = function (TaskId) {
        //Some times outcome field's internal name could be different
        //Go to list settings of your Workflow Tasks to verify the internal names of all the fields below
        var data = {
            "__metadata": { "type": "SP.Data.HRTasksListItem" },
            "WorkflowOutcome": "Approved",
            "Status": "Approved",
            "PercentComplete": 1 
        };
        var itemUrl = _spPageContextInfo.webAbsoluteUrl + 
        "/_api/lists/getbyTitle('HRTasks')/items(" + TaskId + ")";
        dataService.post(itemUrl, JSON.stringify(data),TaskId).then(function (response) {
            alert("Approved Successfully");
        });
    };
    $scope.RejectTask = function (TaskId) {
        //Some times outcome field's internal name could be different
        //Go to list settings of your Workflow Tasks to verify the internal names of all the fields below
        var data = {
            "__metadata": { "type": "SP.Data.HRTasksListItem" },
            "WorkflowOutcome": "Rejected",
            "Status": "Rejected",
            "PercentComplete": 1 
        };
        var itemUrl = _spPageContextInfo.webAbsoluteUrl + 
        "/_api/lists/getbyTitle('HRTasks')/items(" + TaskId + ")";
        dataService.post(itemUrl, JSON.stringify(data),TaskId).then(function (response) {
            alert("Rejected Successfully");
        });
    };

This will show the webpart as follows:

By clicking on Approve or Reject button, you can change the status of the tasks.

The whole code will look like the following:

HTML

HTML
<style>
td{border: solid 1px black; padding: 5px;} 
th{border: solid 1px black; padding: 5px;}
</style>

<script type="text/javascript" src="/style library/pnp.min.js"></script>   
<script type="text/javascript" src="/style library/workflow.js"></script>
<table ng-app="mainapp" style="border:solid 1px black; background-color:white;">
    <thead ng-controller="getHRRequest">
        <tr>
            <th>Task Title</th>
            <th>Task Request</th>
            <th>Approval Status</th>
            <th>Link for Approve/Reject</th>
            <th>Approve</th>
            <th>Reject</th>
        </tr>
        <tr ng-repeat="item in items">
            <td>{{item.Title}}</td>
            <td>{{item.Request}}</td>
            <td>
                <div ng-if="item.Approval==16">Approved</div> 
                <div ng-if="item.Approval==15">Cancelled</div> 
                <div ng-if="item.Approval==17">Rejected</div> 
                <div ng-if="item.Approval==2">InProgress</div> 
                <div ng-if="item.Approval==5">Completed</div> 
                <div ng-if="item.Approval==0">NotStarted</div> 
            </td>
            <td><a href="/_layouts/15/WrkTaskIP.aspx?List=cb305ecc-17af-4f08-9d16-5f96195fbe55&
            ID={{item.TaskId}}">Click</a></td>
            <td><a href="#" 
            ng-click="ApproveTask(item.TaskId)">Approve</a></td>
            <td><a href="#" 
            ng-click="RejectTask(item.TaskId)">Reject</a></td>
        </tr>
    </thead>
</table>

JavaScript

JavaScript
var mainapp = angular.module("mainapp", []);
mainapp.controller('getHRRequest', ['$http', 
'dataService', '$scope', function ($http, dataService, $scope) {
    var getHRRequest = _spPageContextInfo.webAbsoluteUrl + 
    "/_api/web/Lists/GetByTitle('HR_Request')/items?$select=ID,Title,
    Request,Approval&$orderby=Modified desc";
    $scope.items = [];
    dataService.get(getHRRequest).then(function (items) {
        $scope.items = items.data.d.results;
        angular.forEach(items.data.d.results, function (items) {
            var getCurrentUSerId = _spPageContextInfo.webAbsoluteUrl + 
            "/_api/Web/CurrentUser?$select=Id";
            dataService.get(getCurrentUSerId).then(function (users) {
                var getTaskId = _spPageContextInfo.webAbsoluteUrl + 
                "/_api/lists/getbyTitle('HRTasks')/
                items?$select=Id,Title&$filter=WorkflowItemId eq " + 
                items.Id + " and AssignedToId eq " + users.data.d.Id;
                dataService.get(getTaskId).then(function (tasks) {
                    items.TaskId = tasks.data.d.results[0].Id;
                });
            });
        })
    });
    $scope.ApproveTask = function (TaskId) {
        //Some times outcome field's internal name could be different
        //Go to list settings of your Workflow Tasks to verify the internal names of all the fields below
        var data = {
            "__metadata": { "type": "SP.Data.HRTasksListItem" },
            "WorkflowOutcome": "Approved",
            "Status": "Approved",
            "PercentComplete": 1 
        };
        var itemUrl = _spPageContextInfo.webAbsoluteUrl + 
        "/_api/lists/getbyTitle('HRTasks')/items(" + TaskId + ")";
        dataService.post(itemUrl, JSON.stringify(data),TaskId).then(function (response) {
            alert("Approved Successfully");
        });
    };
    $scope.RejectTask = function (TaskId) {
        //Some times outcome field's internal name could be different
        //Go to list settings of your Workflow Tasks to verify the internal names of all the fields below
        var data = {
            "__metadata": { "type": "SP.Data.HRTasksListItem" },
            "WorkflowOutcome": "Rejected",
            "Status": "Rejected",
            "PercentComplete": 1 
        };
        var itemUrl = _spPageContextInfo.webAbsoluteUrl + 
        "/_api/lists/getbyTitle('HRTasks')/items(" + TaskId + ")";
        dataService.post(itemUrl, JSON.stringify(data),TaskId).then(function (response) {
            alert("Rejected Successfully");
        });
    };
}]);

This way, we can update the associated tasks with the listitem with SharePoint REST API.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)