Create custom SharePoint Survey poll using REST API and AngularJS

In this SharePoint bootstrap tutorial, we will discuss how to create a custom Survey poll in SharePoint with REST API and Angular JS.

The code will work in SharePoint Online and SharePoint 2013/2016/2019.

Here I have created a simple web part that can ask you to choose a poll once it gets activated and next it will show you the total output.

Below are a few SharePoint survey tutorials:

Create a custom Survey poll in SharePoint using REST API and AngularJS

Below is the example for creating custom survey poll in SharePoint using REST API and Bootstrap.

Step 1: Before we proceed to write the code, We have to create three lists as per the below screenshot.

Poll Questions List

Create sharepoint survey poll
Create sharepoint survey poll

Poll Symbols

sharepoint survey poll example
sharepoint survey poll example

Poll Logs

sharepoint survey poll
sharepoint survey poll

In Poll Question: Here you have to add your question and answer (Option). After that, we have to activate this question as to the current poll so that It can visible to users.

Poll Symbols: Here we can add the Icon of the poll .

Poll Logs: Here we can store all logs who has already completed the poll.

Step 2: Log in to your SharePoint site -> Add a script editor Web part -> Copy and paste the below code.

<link href="https://pikasha12.sharepoint.com/sites/DLH/Documents/CustomStyle.css">
<link href="https://pikasha12.sharepoint.com/sites/DLH/Documents/css/bootstrap.min.css" rel="stylesheet">

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.6/angular.min.js"></script>
<script>

    var site = "https://pikasha12.sharepoint.com/sites/DLH";
    var PollQuestionslistName = 'Poll Questions';
    var PollLogslistName = 'Poll Logs';
    var appPollResults = angular.module('ng-app-polls', []);
 
//Controller
    appPollResults.controller('pollSubmitCtrl', function ($scope, pollResultsService) {
        $scope.poll = [];

        $scope.getUserDetails = function (pollData) {
            pollResultsService.getUserDetailById(pollData.Question.Id)
                .then(
                    function (isSubmitted) {

                        pollData.result = isSubmitted;
                        $scope.poll = pollData;
                    }
                );
        }

        $scope.getPollsData = function () {
            pollResultsService.getPollDetails(PollQuestionslistName)
                .then(
                    function (pollData) {
                        $scope.getUserDetails(pollData);
                    }
                );
        }

        $scope.pollSubmit = function () {

            pollResultsService.getLoginName()
                .then(
                    function (userLogin) {
                        pollResultsService.setUserDetailById($scope.poll.Question.Id, $scope.poll.selectedAnswer, userLogin)
                            .then(
                                function (success) {
                                    if (success) {
                                        pollResultsService.getItemById($scope.poll.Question.Id)
                                            .then(
                                                function (data1, pollData) {
                                                    var selectedAns = $scope.poll.selectedAnswer;
                                                    pollResultsService.setPollDetails(selectedAns, data1, pollData)
                                                        .then(
                                                            function (success) {
                                                                if (success) {
                                                                    pollResultsService.getPollDetails(PollQuestionslistName)
                                                                        .then(
                                                                            function (pollData) {
                                                                                pollData.result = true;
                                                                                $scope.poll = pollData;
                                                                            });
                                                                }
                                                            }
                                                        );
                                                }
                                            );
                                    } else {
                                        alert('unknown error occured');
                                    }
                                });
                    });
        }

        $scope.getPollsData();

        $scope.selectedIndex = null;
        $scope.selectedAnswer = function (index) {
            $scope.selectedIndex = index;
        }

    });
 
//Services
appPollResults.service(
        'pollResultsService',
    function ($http, $q) {
        return ({
            getPollDetails: getPollDetails,
            setPollDetails: setPollDetails,
            setUserDetailById: setUserDetailById,
            getUserDetailById: getUserDetailById,
            getItemById: getItemById,
            getLoginName: getLoginName
        });

        //Get the Poll Question and Answers
        function getPollDetails() {

            var fullUrl = site + "/_api/web/lists/getbytitle('" + PollQuestionslistName + "')/Items?$Select=";
            fullUrl += 'ID,Title,Excellent,VeryGood,Good,CountExcellent,CountVeryGood,CountGood,TotalCount,Symbol/Value&$expand=Symbol&$orderby=ID desc&$filter=Active eq 1&$Top=1';

            var request = $http({
                method: 'Get',
                url: fullUrl,
                headers: { "accept": "application/json;odata=verbose" }
            });

            return (request.then(successGetPollDetails, handleError));
        }

        //Success Poll Details
        function successGetPollDetails(data) {
            var pollData;
            if (data.data.d.results.length > 0) {
                var result = data.data.d.results[0];
                var percent1 = ((result.CountExcellent / result.TotalCount) * 100).toFixed(0) + '%';
                var percent2 = ((result.CountVeryGood/ result.TotalCount) * 100).toFixed(0) + '%';
                var percent3 = ((result.CountGood / result.TotalCount) * 100).toFixed(0) + '%';
               

                pollData = angular.fromJson({
                    "hasData": true,
                    "result": false,
                    "Question": {
                        "Id": result.ID,
                        "Text": result.Title,
                        "Symbol": result.Symbol.Value,
                        "Total": result.TotalCount
                    },
                    "Answers": [{
                        "Id": 1,
                        "Text": result.Excellent,
                        "Count": result.CountExcellent,
                        "Percent": percent1
                    }, {
                        "Id": 2,
                        "Text": result.VeryGood,
                        "Count": result.CountVeryGood,
                        "Percent": percent2
                    }]
                });

                if (result.Good) {
                    var obj = {};
                    obj["Id"] = 3;
                    obj["Text"] = result.Good;
                    obj["Count"] = result.CountGood;
                    obj["Percent"] = percent3;
                    pollData.Answers.push(obj);
                }
               
            } else {
                pollData = angular.fromJson({
                    "hasData": false,
                    "result": false,
                    "Question": {
                        "Id": 0,
                        "Text": "",
                        "Symbol": "",
                        "Total": 0
                    },
                    "Answers": [{}]
                });
            }
            return (pollData);
        }

        //Set the Poll Details
        function setPollDetails(selectedAnsId, data1) {

            var fullUrl = site + "/_api/web/lists/getbytitle('" + PollQuestionslistName + "')/items";
            var itemType = "SP.Data.Poll_x0020_QuestionsListItem";

            var selAns = '';
            var value = '';
            var cat = {
                '__metadata': { "type": itemType }
            };

            if (selectedAnsId == '1') {
                value = data1.data.d.CountExcellent;
                selAns = "CountExcellent";
            } else if (selectedAnsId == '2') {
                value = data1.data.d.CountVeryGood;
                 selAns = "CountVeryGood";
            } 
               else {
                value = data1.data.d.CountGood;
                 selAns = "CountGood";
                }

                cat[selAns] = value + 1;
                cat['TotalCount'] = data1.data.d.TotalCount + 1;

                var request = $http({
                    url: data1.data.d.__metadata.uri,
                    method: "POST",
                    data: JSON.stringify(cat),
                    headers: {
                        "Accept": "application/json;odata=verbose",
                        "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                        "X-HTTP-Method": "MERGE",
                        "Content-Type": "application/json;odata=verbose",
                        "If-Match": data1.data.d.__metadata.etag
                    }
                });


                return (request.then(successSetPollDetails, handleError));
            }

            function successSetPollDetails(data) {

                return true;
            }

            //Set the Poll Details
            function setUserDetailById(QuestionId, selectedAnswer, userLogin) {

                var fullUrl = site + "/_api/web/lists/getbytitle('" + PollLogslistName + "')/items";
                var itemType = "SP.Data.Poll_x0020_LogsListItem";

                var cat = {
                    "__metadata": { "type": itemType },
                    "Title": userLogin.UserName,
                    "loginid": userLogin.UserId,
                    "userid": _spPageContextInfo.userId,
                    "SelectedAnswer": String(selectedAnswer),
                    "QuestionId": String(QuestionId)
                };

                var request = $http({
                    url: fullUrl,
                    method: "POST",
                    data: JSON.stringify(cat),
                    headers: {
                        "Accept": "application/json;odata=verbose",
                        "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                        "Content-Type": "application/json;odata=verbose"
                    }
                });

                return (request.then(successSetUserDetailById, handleError));
            }

            function successSetUserDetailById(data) {
                return true;
            }

            function getUserDetailById(itemID) {

                var fullUrl = site + "/_api/web/lists/getbytitle('" + PollLogslistName + "')/Items?$Select=";
                fullUrl += "Title,QuestionId&$filter=userid eq '" + _spPageContextInfo.userId + "' and QuestionId eq '" + itemID + "'&$top=1";

                var request = $http({
                    method: 'Get',
                    url: fullUrl,
                    headers: { "accept": "application/json;odata=verbose" }
                });

                return (request.then(successGetUserDetailById, handleError));
            }

            function successGetUserDetailById(data) {
                if (data.data.d.results.length > 0) {
                    return true;
                } else {
                    return false;
                }

            }

            function getItemById(itemID) {

                var fullUrl =site + "/_api/web/lists/getbytitle('" + PollQuestionslistName + "')/Items('" + itemID + "')";

                var request = $http({
                    url: fullUrl,
                    Method: "POST",
                    headers: { "accept": "application/json;odata=verbose" },
                });

                return (request.then(successGetItemById, handleError));
            }

            function successGetItemById(data) {
                return data;
            }

            function getLoginName() {
                var userid = _spPageContextInfo.userId;
                var fullUrl = site + "/_api/web/getuserbyid(" + userid + ")";

                var request = $http({
                    url: fullUrl,
                    contentType: "application/json;odata=verbose",
                    Method: "GET",
                    headers: { "accept": "application/json;odata=verbose" },
                });

                return (request.then(successGetLoginName, handleError));
            }

            function successGetLoginName(data) {
                var lname = data.data.d.LoginName;
                lname = lname.split("|")[1];
                var userLogin = {
                    "UserName": data.data.d.Title,
                    "UserId": lname,
                    "Email": data.data.d.Email
                }
                return userLogin;
            }

            //Handle Error
            function handleError(response) {

                if (
                    !angular.isObject(response.data) ||
                    !response.data.message
                ) {
                    return ($q.reject("An unknown error occurred."));
                }
                // Otherwise, use expected error message.
                return ($q.reject(response.data.message));
            }
        }   
);
</script>



<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fjquery%2F1.11.2%2Fjquery.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
 <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.4.5%2Fangular.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
 <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fsites%2FStyle%2520Library%2Fjs%2Fmain.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
 
     
<div data-ng-app="ng-app-polls">
         
<div data-ng-controller="pollSubmitCtrl">
             
<div>
                 
<div class="panel panel-primary" data-ng-show="poll.hasData">
                     
<div class="panel-heading">
                         
<h3 class="panel-title"><i class="fa fa-lg {{poll.Question.Symbol}}"></i>{{poll.Question.Text}}</h3>
 
                    </div>
 
                     
<div data-ng-show="!poll.result">
                         
<div class="panel-body">
                             
<ul class="list-group ulpoll">
                                 
<li class="list-group-item" data-ng-repeat="answer in poll.Answers" data-ng-style="{ 'background-color' : $index == selectedIndex ? '#f5f5f5' : '' }" data-ng-click="selectedAnswer($index)">
 
<div class="radio">
                                        <label>
                                            <input type="radio" data-ng-model="poll.selectedAnswer" data-ng-value="{{ answer.Id }}" name="radioPollAnswers">
                                            {{ answer.Text }}
                                        </label>
                                    </div>
 
                                </li>
 
                            </ul>
 
                        </div>
 
                         
<div class="panel-footer text-center">
                            <button type="button" class="btn btn-success btn-md" data-ng-disabled="!poll.selectedAnswer" data-ng-click="pollSubmit()">
                                <span class="fa fa-check-square-o fa-lg"></span>Vote
                            </button>
                        </div>
 
                    </div>
 
                     
<div data-ng-show="poll.result">
                         
<div class="panel-body">
                             
<ul class="list-group ulpoll">
                                 
<li class="list-group-item" data-ng-repeat="answer in poll.Answers">
 
<div class="pollAnswer">
                                        <span>{{ answer.Text }}</span><span class="pollPercent">{{answer.Percent}}</span>
                                    </div>
 
                                     
<div class="progress">
                                         
<div class="progress-bar" role="progressbar" aria-valuenow="{{ answer.Count }}" aria-valuemin="0" aria-valuemax="100" data-ng-style="{'width': answer.Percent}">
                                            <span class="sr-only">{{answer.Percent}}</span>
                                        </div>
 
                                    </div>
 
                                </li>
 
                            </ul>
 
                        </div>
 
                         
<div class="panel-footer">
                             
<div data-ng-show="poll.result">                                 
Total - {{ poll.Question.Total }}
 
                            </div>
 
                        </div>
 
                    </div>
 
                </div>
             <div data-ng-show="!poll.hasData">
                     
<div class="alert alert-danger" role="alert">No Active Poll for now.</div>
 
                </div>
 
            </div>
 
        </div>
 
    </div>

Step 3: If you have not completed the poll then it will ask you to complete the poll. Below is the screenshot of my poll.

sharepoint survey examples
sharepoint survey examples

Step 4: Once you have completed your poll then the list data will show like as the below screenshot.

image 27
sharepoint online survey examples
sharepoint online survey examples

Note: Initially the CountExcellent, CountVeryGood and CountGood column data will be empty. Once the user completed the poll, it will increase automatically. But before activating this poll, you have to fill the question and answer column.

Step 5: Once you have completed your poll, you can able to see the below screen as per this snapshot.

create custom sharepoint survey poll using rest api and angularjs
create custom sharepoint survey poll using rest api and angularjs

You may like the following SharePoint rest api tutorials:

This is all about a custom poll in SharePoint. Please try and put your comment here if you have any issues. Make sure you are referring to proper CSS and script files before going to start.

  • >