Reputation: 180
I was working on a quiz application in Angular JS, more like the quiz up application where you can have a timed quiz consisting of questions, each question giving you 10 seconds to answer.I have completed making a quiz application which allows me to answer questions and at the end giving results but i am stuck on the problem of how I can introduce a timer for each of my questions? Do i have to make a separate directive or a controller? The problem is that the timer requires a $timeout function which creates a delay but that creates a delay in my application altogether. Any help?
Note : I am a beginner in Angular JS.
app.js :
var app = angular.module('TheQuiz',[]);
app.controller('QuizControl',['$scope','$http','$sce','$timeout',function($scope,$http,$sce,$timeout){
$scope.score = 0;
$scope.presentQues = -1;
$scope.presentQuesAnswered = 0;
$scope.percent = 0;
$scope.playername = $scope.playername;
$scope.myself = false;
$http.get('getdata.php').then(function(qData){
$scope.Questions = qData.data;
$scope.fullQuestions = $scope.Questions.length;
});
$scope.startQuiz = function(){
if ($scope.playername.length){
$scope.presentQues = 0;
}
}
$scope.restart = function(){
$scope.score = 0;
$scope.presentQues = -1;
$scope.presentQuesAnswered = 0;
$scope.percent = 0;
$scope.playername = "";
$http.get('getdata.php').then(function(qData){
$scope.Questions = qData.data;
$scope.fullQuestions = $scope.Questions.length;
});
}
$scope.selectAns = function(pIndex , rIndex){
var quesState = $scope.Questions[pIndex].quesState;
if ( quesState != 'answered' ){
$scope.Questions[pIndex].selectedAns = rIndex;
var rightAns = $scope.Questions[pIndex].correct;
$scope.Questions[pIndex].rightAns = rightAns;
if (rIndex === rightAns){
$scope.Questions[pIndex].correctness = 'correct';
$scope.score += 1;
}
else {
$scope.Questions[pIndex].correctness = 'incorrect';
}
$scope.Questions[pIndex].quesState = "answered";
}
$scope.percentage = (($scope.score / $scope.fullQuestions) * 100).toFixed(2);
}
$scope.yesselected = function(pIndex , rIndex){
return $scope.Questions[pIndex].selectedAns === rIndex;
}
$scope.yescorrect = function(pIndex , rIndex){
return $scope.Questions[pIndex].rightAns === rIndex;
}
$scope.Continue = function(){
return $scope.presentQues += 1;
}
$scope.Pass = function(){
return $scope.presentQues += 1;
}
}]);
Upvotes: 1
Views: 1218
Reputation: 629
Your best bet when working with time in Javascript is to use the moment.js library. It makes life a lot easier.
I've built this using Angular 1.5.x and used a component.
Here's a link to a working version.
I've added a couple of properties on the component for ease of use but of course this can be hidden from users if needed. Simply set the amount and the unit. i.e for 10 hour countdown, simply set cmp-from to 10 and cmp-unit to hour. These values mimic the format() method in the moment()
library using the add() method.
I've also added an onEnd method so that any parent controller can be notified of the timer ending.
This is purely for demoing purposes only, ideally this should follow a more functional programming approach for production.
Usage:
<cmp-timer
cmp-from="10"
cmp-unit="second"
cmp-on-end="$ctrl.doSomething()">
</cmp-timer>
Component:
angular
.module('app', [])
.component('cmpTimer', {
bindings: {
cmpFrom: '<',
cmpUnit: '@',
cmpOnEnd: '&'
},
template: '<div class="timer">{{$ctrl.timeRemaining}}</div>',
controller: function ($interval) {
var vm = this, ONE_SECOND = 1000, timerInterval;
function startTimer() {
var END_TIME = vm.getEndTime();
function update() {
vm.timeRemaining = moment((moment(END_TIME) - moment())).format("HH:mm:ss");
}
timerInterval = $interval(function() {
if (moment() > moment(END_TIME)) return vm.stopTimer();
update();
}, ONE_SECOND);
update();
}
vm.getEndTime = function() {
return moment().add(vm.cmpFrom, vm.cmpUnit);
}
vm.stopTimer = function() {
alert('Time\'s up!');
vm.cmpOnEnd();
vm.$onDestroy();
}
vm.$onDestroy = function() {
$interval.cancel(timerInterval);
}
vm.$onInit = startTimer;
}
});
The approach I would recommend would be to have an outer controller/view and use ngIf
to show or hide the cmp-timer whenever your ready to do so.
Upvotes: 2