Customizing #Episerver.Forms with client events, build a quiz

Example of using client side events to tweak and customize the output and displaying result depending of input values.

icon of user profile

Published 27th of October 2017
Episerver Forms > v2

Storyboard:

  • quiz
  • multiple steps
  • last step display result
  • and possibility to post your result (on a board or for a contest)

Demo in full screen (gif)

We will use the jQuery formsSetupCompleted and formsNavigationNextStep to do our client side customizations.

Available events are:

  • formsNavigationNextStep
  • formsNavigationPrevStep
  • formsSetupCompleted
  • formsReset
  • formsStartSubmitting
  • formsSubmitted
  • formsSubmittedError
  • formsNavigateToStep
  • formsStepValidating

This example uses this setup:

On the question (single choice) elements i choosed to set 1 (one) for the right answer and 0 (zero) on wrong.

Then later in the javascript I just sum radio buttons in form and divide with total radios, so I get a percent.

The Rich Text Element in result step displays a progress bar and then uncovers a div depending on result in previous steps:

<div class="result full">
<div class="progress">
<div class="progress-bar" style="width: 0%;">&nbsp;</div>
</div>
<div class="resulttext">
<h4 style="font-size: 50px;"><span style="color: lightgray;">Good</span> <span style="color: lightgray;">Better</span> Best</h4>
<p>You are simply the best, you should come work with us! Please supply your contact information and we will but you on our ranking board.&nbsp;</p>
</div>
</div>
<div class="result half">
<div class="progress">
<div class="progress-bar" style="width: 0%;">&nbsp;</div>
</div>
<div class="resulttext">
<h4 style="font-size: 50px;"><span style="color: lightgray;">Good</span> Better&nbsp;<span style="color: lightgray;">Best</span></h4>
<p>Thats a great result, most devs doesn't even come this far!&nbsp;</p>
</div>
</div>
<div class="result zero">
<div class="progress">
<div class="progress-bar" style="width: 0%;">&nbsp;</div>
</div>
<div class="resulttext">
<h4 style="font-size: 50px;">Good <span style="color: lightgray;">Better</span> <span style="color: lightgray;">Best</span></h4>
<p>You seem competent, but maybe you should try again.&nbsp; &nbsp;</p>
</div>
</div>
<h3>Supply your score to our ranking board</h3>

Result_Percent and Result_Grade: I use predefined hidden inputs to save the score when submitted.

After submission:

Back-end:

<div class="result half full">
<h1>Thank you</h1>
<p>We will put you on our ranking board</p>
</div>
<div class="result zero">
<h1>To bad you didn't make it</h1>
<p>Better luck next time!</p>
</div>

Display:

The code:

Made a quizblock just to package form with javascript, I use it to ouput my javascript, only on pages when this block is used, thru EPiServer.Framework.Web.Resources.ClientResources.RequireScript(“/static/js/quizblock.js”).AtFooter();

@model Gosso.Models.Blocks.QuizBlock

@{
    EPiServer.Framework.Web.Resources.ClientResources.RequireScript("/static/js/quizblock.js").AtFooter();
}
<div class="quizBlock">

    @Html.PropertyFor(x => x.TopContentArea, new { CssClass = "row block-container" })

</div>
using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;

namespace Gosso.Models.Blocks
{
    [ContentType(
       DisplayName = "Quiz block",
       Description = "Block to create Quiz with Episerver Forms",
       GroupName = SystemTabNames.Content,
       AvailableInEditMode = true)]
    public class QuizBlock : BlockData
    {

        [Display(
            Name = "Block full width",
            GroupName = SystemTabNames.Content,
            Order = 8
        )]
        public virtual ContentArea TopContentArea { get; set; }

    }
}

The javascript

if (typeof $$epiforms !== 'undefined') {
    $$epiforms(document).ready(function myfunction() {

        var ShowResult = function ($htmlblock, procent) {

            $htmlblock.find("h4,p").hide();
            $htmlblock.show();
            $htmlblock.find(".progress .progress-bar").animate({
                width: procent + "%"
            }, 800);

            setTimeout(function () { $htmlblock.find("h4").slideDown(); }, 1800);
            setTimeout(function () { $htmlblock.find("p").slideDown(); }, 2800);
        };
        $(".EPiServerForms .result").hide();//hide everything on init

        var formResult = "Good";

        $$epiforms(".EPiServerForms").on("formsNavigationNextStep formsNavigationPrevStep formsSetupCompleted formsReset formsStartSubmitting formsSubmitted formsSubmittedError formsNavigateToStep formsStepValidating", function (event, param1, param2) {
            console.log(event.type, event); //for fun
            //which step am i on?
            var lastStep = (event.targetStep!== undefined && event.workingFormInfo.StepsInfo.Steps.length === event.targetStep.index + 1);
            var firstStep = (event.targetStep !== undefined && event.targetStep.index===0);

            if (event.type === "formsSubmitted" && event.isFinalizedSubmission) {
                //cool, its submitted, setTimeout because AJAX call
                setTimeout('filterQuizResult("' + formResult + '")', 100);
            }
            else if (event.type === "formsNavigationNextStep") {
                if (lastStep) {
                    //Count the score
                    var summa = 0;
                    var counter = 0;
                    //for each radiobutton in this form
                    $(this).find(".FormChoice__Input--Radio:checked").each(function() {
                        counter++;
                        summa = eval(summa + parseInt(this.value));
                    });

                    var procent = summa / counter * 100;
                    console.log("formsNavigationNextStep sum", summa);
                    console.log("formsNavigationNextStep count", counter);
                    console.log("formsNavigationNextStep procent", procent);

                    $(this).find(".result").hide();//initial
                    if (procent >= 100) { //depending on percent
                        ShowResult($(this).find(".result.full"), 100);
                        formResult = "Best";

                    } else if (procent > 66) {
                        ShowResult($(this).find(".result.half"), procent);
                        formResult = "Better";
                    } else {
                        ShowResult($(this).find(".result.zero"), procent);
                        formResult = "Good";
                    }

                    $(this).find(".Form__Element.FormHidden").val(procent); //save to hidden element
                    $(this).find(".Form__Element.FormHidden.Result_Grade").val(formResult); //save to hidden element
                    $(this).find(".btnNext").hide();
                }

                 $(this).find(".btnPrev").show();
            }
            else if (event.type === "formsSetupCompleted") { //setup complete, customize the navigationbar
                $(this).find(".btnPrev").hide();
                $(this).find(".Form__NavigationBar__ProgressBar--Progress").hide();
                $(this).find(".Form__NavigationBar__ProgressBar").hide();

                $(this).find(".FormChoice__Input--Radio:checked").each(function () {
                    this.checked = ""; //default reseting
                });

            }
            else if (event.type === "formsNavigationPrevStep" || event.type === "formsReset") {
                if (firstStep)
                    $(this).find(".btnPrev").hide();//dont show on firststep
                $(this).find(".btnNext").show();
            }
        });
    });
}

function filterQuizResult(formResult) {
    if ($(".Form__Success__Message").length > 0) { // check if message exists
        $(".EPiServerForms .Form__Success__Message .result.full").hide();
        if (formResult !== "Good") {
            $(".EPiServerForms .Form__Success__Message .result").hide();
            $(".EPiServerForms .Form__Success__Message .result.full").show();
        } else {
            $(".EPiServerForms .Form__Success__Message .result.zero").show();
        }
    } else {
        setTimeout('filterQuizResult("' + formResult + '")', 100);//test again
    }
}

Javascript console:

Email the submission looks like this:

Thoughts

Source:

SEO terms

  • Extending Episerver Forms Example
  • jQuery events client side tweaking

Happy forming!