{"id":262,"date":"2014-12-05T02:48:35","date_gmt":"2014-12-04T21:18:35","guid":{"rendered":"http:\/\/odhyan.com\/blog\/?p=262"},"modified":"2017-04-04T15:27:58","modified_gmt":"2017-04-04T09:57:58","slug":"building-a-simple-quiz-app-using-angularjs","status":"publish","type":"post","link":"https:\/\/odhyan.com\/blog\/2014\/12\/building-a-simple-quiz-app-using-angularjs\/","title":{"rendered":"Building a Simple Quiz App using AngularJS"},"content":{"rendered":"<p>AngularJS has been out there for quite a while now and is getting increasingly popular. It is a very powerful Javascript MVC framework for building well-structured and maintainable web applications. <\/p>\n<p>This tutorial is not an introduction to AngularJS but to demonstrate how quickly one can build a simple well-structured web application. This is targeted towards people who are already familiar with the basics of AngularJS.<\/p>\n<p>The app will have a very simple structure &#8211; a single page app, one question at a time on the screen with four options, a submit button and score. For simplicity, there is no database of questions, instead we define a set of questions in the app itself. <a href=\"http:\/\/odhyan.com\/quizapp-angular\/\">This will be the final output<\/a>. <\/p>\n<p>Let&#8217;s start building.<\/p>\n<p>We need two html files for markup, one will have the main markup and the other will have the template for our quiz section. Let&#8217;s call them index.html and template.html. We also need an app.js file which will have our app logic and a style.css. <\/p>\n<p>The markup in index.html is straightforward.<\/p>\n<pre lang=\"html4strict\">\r\n<!DOCTYPE html>\r\n<html ng-app=\"quizApp\">\r\n    <head>\r\n        <meta charset=\"utf-8\" \/>\r\n        <title>QuizApp<\/title>\r\n        <link rel=\"stylesheet\" href=\"style.css\" \/>\r\n        <script src=\"http:\/\/code.jquery.com\/jquery-2.0.3.min.js\"><\/script>\r\n        <script src=\"https:\/\/ajax.googleapis.com\/ajax\/libs\/angularjs\/1.0.8\/angular.min.js\"><\/script>\r\n        <script src=\"app.js\"><\/script>\r\n    <\/head>\r\n\r\n    <body>\r\n        <div class=\"container\">\r\n            <h1 class=\"title\">QuizApp<\/h1>\r\n            <quiz\/>\r\n        <\/div>\r\n    <\/body>\r\n<\/html>\r\n<\/pre>\n<p>The only two interesting things here are the <em>ng-app<\/em> attribute and the <em>quiz<\/em> tag. We will define a custom directive for the <em>quiz<\/em> tag later. Let&#8217;s go to the template now. The quiz template will replace the <em>quiz<\/em> tag above. It consists of 2 sections: a quiz section when the quiz is in progress and an intro section when the quiz app is loaded initially.<\/p>\n<pre lang=\"html4strict\">\r\n<div class=\"quiz-area\" ng-show=\"inProgress\">\r\n<\/div>\r\n\r\n<div class=\"intro\" ng-show=\"!inProgress\">\r\n\t<p>Welcome to the QuizApp<\/p>\r\n\t<button id=\"startQuiz\" ng-click=\"start()\">Start the Quiz<\/button>\r\n<\/div>\r\n<\/pre>\n<p>As you notice, we used two built-in directives here: <em>ng-show<\/em> and <em>ng-click<\/em>. <em>inProgress<\/em> and <em>start()<\/em> will be defined later but are self-explanatory. In the quiz area, we either show a question or a message when the quiz is over. We also need a section for score.<\/p>\n<pre lang=\"html4strict\">\r\n<div class=\"quiz-area\" ng-show=\"inProgress\">\r\n\t<div ng-show=\"!quizOver\">\r\n\t<\/div>\r\n\r\n\t<div ng-show=\"quizOver\">\r\n\t\t<h2>Quiz is over<\/h2>\r\n\t\t<button ng-click=\"reset()\">Play again<\/button>\r\n\t<\/div>\r\n\r\n\t<div id=\"score\">\r\n\t<\/div>\r\n<\/div>\r\n<\/pre>\n<p>In app.js we defined a custom directive called <em>quiz<\/em>. It looks like below:<\/p>\n<pre lang=\"javascript\">\r\nvar app = angular.module('quizApp', []);\r\n\r\napp.directive('quiz', function() {\r\n    return {\r\n\trestrict: 'AE',\r\n\tscope: {},\r\n\ttemplateUrl: 'template.html',\r\n\tlink: function(scope, elem, attrs) {\r\n\t    \/\/TODO\r\n\t}\r\n    }\r\n});\r\n<\/pre>\n<p>Now we need some methods to start a quiz, get a question and check the answer.<\/p>\n<pre lang=\"javascript\">\r\nvar app = angular.module('quizApp', []);\r\n\r\napp.directive('quiz', function(quizFactory) {\r\n\treturn {\r\n\t\trestrict: 'AE',\r\n\t\tscope: {},\r\n\t\ttemplateUrl: 'template.html',\r\n\t\tlink: function(scope, elem, attrs) {\r\n\t\t\tscope.start = function() {\r\n\t\t\t};\r\n\r\n\t\t\tscope.getQuestion = function() {\r\n\t\t\t};\r\n\r\n\t\t\tscope.checkAnswer = function() {\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n});\r\n<\/pre>\n<p>Let&#8217;s implement these methods now. <\/p>\n<pre lang=\"javascript\">\r\nscope.start = function() {\r\n\tscope.id = 0;\r\n        scope.quizOver = false;\r\n\tscope.inProgress = true;\r\n\tscope.getQuestion();\r\n};\r\n<\/pre>\n<p>Here <em>scope.id<\/em> is the id of the current question. We used <em>inProgress<\/em> in the template and it will be true while the quiz is running.<\/p>\n<p>To get a question, we need a source. We create a factory to get the questions. The factory will return a question when a given question id is requested. <\/p>\n<pre lang=\"javascript\">\r\napp.factory('quizFactory', function() {\r\n\tvar questions = [\r\n\t\t{\r\n\t\t\tquestion: \"Which is the largest country in the world by population?\",\r\n\t\t\toptions: [\"India\", \"USA\", \"China\", \"Russia\"],\r\n\t\t\tanswer: 2\r\n\t\t},\r\n\t\t{\r\n\t\t\tquestion: \"When did the second world war end?\",\r\n\t\t\toptions: [\"1945\", \"1939\", \"1944\", \"1942\"],\r\n\t\t\tanswer: 0\r\n\t\t},\r\n\t\t{\r\n\t\t\tquestion: \"Which was the first country to issue paper currency?\",\r\n\t\t\toptions: [\"USA\", \"France\", \"Italy\", \"China\"],\r\n\t\t\tanswer: 3\r\n\t\t},\r\n\t\t{\r\n\t\t\tquestion: \"Which city hosted the 1996 Summer Olympics?\",\r\n\t\t\toptions: [\"Atlanta\", \"Sydney\", \"Athens\", \"Beijing\"],\r\n\t\t\tanswer: 0\r\n\t\t},\r\n\t\t{\t\r\n\t\t\tquestion: \"Who invented telephone?\",\r\n\t\t\toptions: [\"Albert Einstein\", \"Alexander Graham Bell\", \"Isaac Newton\", \"Marie Curie\"],\r\n\t\t\tanswer: 1\r\n\t\t}\r\n\t];\r\n\r\n\treturn {\r\n\t\tgetQuestion: function(id) {\r\n\t\t\tif(id < questions.length) {\r\n\t\t\t\treturn questions[id];\r\n\t\t\t} else {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n});\r\n<\/pre>\n<p>Now we can implement the <em>getQuestion()<\/em> method in our quiz directive.<\/p>\n<pre lang=\"javascript\">\r\nscope.getQuestion = function() {\r\n\tvar q = quizFactory.getQuestion(scope.id);\r\n\tif(q) {\r\n\t\tscope.question = q.question;\r\n\t\tscope.options = q.options;\r\n\t\tscope.answer = q.answer;\r\n\t} else {\r\n\t\tscope.quizOver = true;\r\n\t}\r\n};\r\n<\/pre>\n<p>Now we can go back to our template and fill the details. <\/p>\n<pre lang=\"html4strict\">\r\n<div class=\"quiz-area\" ng-show=\"inProgress\">\r\n\t<div ng-show=\"!quizOver\">\r\n\t\t<h2 id=\"question\">{{question}}<\/h2>\r\n\t\t<ul id=\"options\">\r\n\t\t\t<li ng-repeat=\"option in options\">\r\n\t\t\t\t<label>\r\n\t\t\t\t\t<input type=\"radio\" name=\"answer\" value=\"{{option}}\">\r\n\t\t\t\t\t{{option}}\r\n\t\t\t\t<\/label>\r\n\t\t\t<\/li>\r\n\t\t<\/ul>\r\n\t\t<button ng-click=\"checkAnswer()\" ng-show=\"answerMode\">Submit<\/button>\r\n\r\n                <div ng-show=\"!answerMode\">\r\n\t\t\t<button ng-click=\"nextQuestion()\" class=\"next-question\">Next<\/button>\r\n\t\t\t<span ng-show=\"correctAns\">That is correct!<\/span>\r\n\t\t\t<span ng-show=\"!correctAns\">Sorry, that is an incorrect answer.<\/span>\r\n\t\t<\/div>\r\n\t<\/div>\r\n\r\n\t<div ng-show=\"quizOver\">\r\n\t\t<h2>Quiz is over<\/h2>\r\n\t\t<button ng-click=\"reset()\">Play again<\/button>\r\n\t<\/div>\r\n\r\n\t<div id=\"score\">\r\n\t\tScore: {{score}}\r\n\t<\/div>\r\n<\/div>\r\n<\/pre>\n<p>The <em>checkAnswer()<\/em> method needs to compare the selected option with the correct answer. We also need <em>answerMode<\/em> so we display the options or the result of current question accordingly. When the user clicks 'Next', we need to go to the next question. <em>nextQuestion()<\/em> does that. Our <em>quiz<\/em> directive looks like below now:<\/p>\n<pre lang=\"javascript\">\r\napp.directive('quiz', function(quizFactory) {\r\n\treturn {\r\n\t\trestrict: 'AE',\r\n\t\tscope: {},\r\n\t\ttemplateUrl: 'template.html',\r\n\t\tlink: function(scope, elem, attrs) {\r\n\t\t\tscope.start = function() {\r\n\t\t\t\tscope.id = 0;\r\n\t\t\t\tscope.quizOver = false;\r\n\t\t\t\tscope.inProgress = true;\r\n\t\t\t\tscope.getQuestion();\r\n\t\t\t};\r\n\r\n\t\t\tscope.reset = function() {\r\n\t\t\t\tscope.inProgress = false;\r\n\t\t\t\tscope.score = 0;\r\n\t\t\t}\r\n\r\n\t\t\tscope.getQuestion = function() {\r\n\t\t\t\tvar q = quizFactory.getQuestion(scope.id);\r\n\t\t\t\tif(q) {\r\n\t\t\t\t\tscope.question = q.question;\r\n\t\t\t\t\tscope.options = q.options;\r\n\t\t\t\t\tscope.answer = q.answer;\r\n\t\t\t\t\tscope.answerMode = true;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tscope.quizOver = true;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tscope.checkAnswer = function() {\r\n\t\t\t\tif(!$('input[name=answer]:checked').length) return;\r\n\r\n\t\t\t\tvar ans = $('input[name=answer]:checked').val();\r\n\r\n\t\t\t\tif(ans == scope.options[scope.answer]) {\r\n\t\t\t\t\tscope.score++;\r\n\t\t\t\t\tscope.correctAns = true;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tscope.correctAns = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tscope.answerMode = false;\r\n\t\t\t};\r\n\r\n\t\t\tscope.nextQuestion = function() {\r\n\t\t\t\tscope.id++;\r\n\t\t\t\tscope.getQuestion();\r\n\t\t\t}\r\n\r\n\t\t\tscope.reset();\r\n\t\t}\r\n\t}\r\n});\r\n<\/pre>\n<p>As we see, within 100 lines of javascript code we built a simple but fully functional quiz app. Also the markup is pretty expressive and anybody going through it can grasp the logic fairly quickly. That's the beauty of AngularJS \ud83d\ude42<\/p>\n<p><a href=\"http:\/\/odhyan.com\/quizapp-angular\/\">You can see the implementation here.<\/a><br \/>\nThe full source code can be viewed at <a href=\"https:\/\/github.com\/odhyan\/quizapp-angular\">my GitHub repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>AngularJS has been out there for quite a while now and is getting increasingly popular. It is a very powerful Javascript MVC framework for building well-structured and maintainable web applications. This tutorial is not an introduction to AngularJS but to demonstrate how quickly one can build a simple well-structured web application. This is targeted towards&hellip;<\/p>\n <a href=\"https:\/\/odhyan.com\/blog\/2014\/12\/building-a-simple-quiz-app-using-angularjs\/\" title=\"Building a Simple Quiz App using AngularJS\" class=\"entry-more-link\"><span>Read More<\/span> <span class=\"screen-reader-text\">Building a Simple Quiz App using AngularJS<\/span><\/a>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[10],"class_list":["entry","author-saurabh","post-262","post","type-post","status-publish","format-standard","category-programming","tag-javascript"],"_links":{"self":[{"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/posts\/262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/comments?post=262"}],"version-history":[{"count":12,"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/posts\/262\/revisions"}],"predecessor-version":[{"id":274,"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/posts\/262\/revisions\/274"}],"wp:attachment":[{"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/media?parent=262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/categories?post=262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/odhyan.com\/blog\/wp-json\/wp\/v2\/tags?post=262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}