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:
- PowerApps Employee Engagement Survey Example
- Working with Survey List in SharePoint 2016/2013 or SharePoint Online
- Create a Survey in SharePoint Online or SharePoint 2013/2016/2019
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
Poll Symbols
Poll Logs
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="<script>" title="<script>" />
<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="<script>" title="<script>" />
<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="<script>" title="<script>" />
<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.
Step 4: Once you have completed your poll then the list data will show like as the below screenshot.
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.
You may like the following SharePoint rest api tutorials:
- Retrieve and Display TASK status using REST API in SharePoint
- Create Highcharts in SharePoint using Rest API
- Retrieve list data using AngularJS REST API in SharePoint 2013
- Bind SharePoint list items to the drop-down list using Rest api and jQuery in SharePoint 2013
- The security validation for this page is invalid and might be corrupted error in SharePoint 2013 Rest API
- SharePoint Rest API: Create or Delete the folder from a document library
- How to update person or group column in SharePoint rest api
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.
Rajkiran is currently working as a SharePoint Consultant in India . Rajkiran having 7+ years of experience in Microsoft Technologies such as SharePoint 2019/2016/2013/2010, MOSS 2007,WSS 3.0, Migration, Asp.Net, C#.Net, Sql Server, Ajax, jQuery etc.He is C#Corner MVP (2 Times).
[…] Create custom SharePoint Survey poll using REST API and AngularJS […]
[…] Create custom SharePoint Survey poll using REST API and AngularJS […]