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.

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!

1 thought on “Customizing #Episerver.Forms with client events, build a quiz”

Leave a Reply

Your email address will not be published. Required fields are marked *