How to go the next page of a form with JavaScript?

I made a subscription form. I divided questions in four pages and I am trying to use JavaScript code in order to hide pages and show the page I am going to with Next button. It worked well when I only had Next buttons. But from the moment I added Previous buttons, it don’t have the expected effect : I can go to the second part of the form but at the second click (on Previous or Next button), all parts of the form disappear.

How is it possible to make it work ?

html.twig

{% extends 'base.html.twig' %}

{% block title %}Incris-toi !{% endblock %}

{% block main %}

<main class="form container">

    <header></header>

    {{form_start(userform)}}

        <div class="formpage page1">
            <div class="form-floating mb-3">
                {{form_widget(userform.email, {'attr' : {'placeholder' : 'Mon adresse e-mail', 'class' : 'form-control'}})}}
                {{form_label(userform.email, 'Mon adresse e-mail', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.password.first, {'attr' : {'placeholder' : 'Mon mot de passe', 'class' : 'form-control'}})}}
                {{form_label(userform.password.first, 'Mon mot de passe', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating">
                {{form_widget(userform.password.second, {'attr' : {'placeholder' : 'Confirmation de mon mot de passe', 'class' : 'form-control'}})}}
                {{form_label(userform.password.second, 'Confirmation de mon mot de passe', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-checkbox">
                {{form_widget(userform.roles)}}
                <span class="checkbox"></span>
                <span class="checkmark"></span>
            </div>
            <button type="button" class="next btn btn-lg btn-outline-primary mt-4 d-flex mx-auto">Je m'inscris</button>
        </div>
        <div class="formpage page2">
            <h1 class="display-1 align-items-center mb-4">Pour savoir qui tu es.</h1>
            <div class="form-floating mb-3">
                {{form_widget(userform.gender, {'attr' : {'placeholder' : 'Es-tu un homme ou une femme ?', 'class' : 'form-control'}})}}
                {{form_label(userform.gender, 'Es-tu un homme ou une femme ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.firstname, {'attr' : {'placeholder' : 'Quel est ton prénom ?', 'class' : 'form-control'}})}}
                {{form_label(userform.firstname, 'Quel est ton prénom ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.lastname, {'attr' : {'placeholder' : 'Quel est ton nom de famille ?', 'class' : 'form-control'}})}}
                {{form_label(userform.lastname, 'Quel est ton nom de famille ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                <p>Quelle est ta date de naissance ?</p>
                {{form_widget(userform.birthdate, {'select' : {'class' : 'form-select'}})}}
            </div>
            <div class="d-flex">
                <button type="button" class="prev btn btn-lg btn-outline-primary mt-4 d-flex me-auto">Précédent</button>
                <button type="button" class="next btn btn-lg btn-outline-primary mt-4 d-flex ms-auto">Suivant</button>
            </div>
        </div>
        <div class="formpage page3">
            <h1 class="display-1 align-items-center mb-4">Pour mieux te connaître.</h1>
            <div class="form-floating mb-3">
                {{form_widget(userform.occupation, {'attr' : {'placeholder' : 'Quelle est ton occupation (ton métier, tes études…) ?', 'class' : 'form-control'}})}}
                {{form_label(userform.occupation, 'Quelle est ton occupation (ton métier, tes études…) ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.nationality, {'attr' : {'placeholder' : 'Quelle est ta nationalité ?', 'class' : 'form-control'}})}}
                {{form_label(userform.nationality, 'Quelle est ta nationalité ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.nativelanguage, {'attr' : {'placeholder' : 'Quelle est ta langue maternelle ?', 'class' : 'form-control'}})}}
                {{form_label(userform.nativelanguage, 'Quelle est ta langue maternelle ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <button type="button" class="next btn btn-lg btn-outline-primary mt-4 d-flex ms-auto">Suivant</button>
        </div>
        <div class="formpage page4">
            <h1 class="display-1 align-items-center mb-4">Et savoir ce que tu viens faire ici.</h1>
            <div class="form-floating mb-3">
                {{form_widget(userform.wishedlanguages, {'attr' : {'placeholder' : 'Quelle(s) langue(s) souhaites-tu pratiquer ?', 'class' : 'form-control'}})}}
                {{form_label(userform.wishedlanguages, 'Quelle(s) langue(s) souhaites-tu pratiquer ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <button class="btn btn-lg btn-outline-primary mt-4 d-flex mx-auto">Je valide mon inscription</button>
        </div>

    {{form_end(userform)}}

</main>

{% endblock %}

{% block js %}

<script src="../assets/js/scripts.js"></script>

{% endblock %}   

scripts.js

const pages = document.querySelectorAll(".formpage")

window.onload = () => {

    document.querySelector(".formpage").style.display = "initial"

    let nextbutton = document.querySelectorAll(".next")

    for(let button of nextbutton) {
        button.addEventListener("click", nextPage)
    }

    let prevbutton = document.querySelectorAll(".prev")

    for(let button of prevbutton) {
        button.addEventListener("click", previousPage)
    }
}

function nextPage(){

    for(let page of pages){
        page.style.display = "none"
    }

    this.parentElement.nextElementSibling.style.display = "initial"
}

function previousPage(){

    for(let page of pages){
        page.style.display = "none"
    }

    this.parentElement.previousElementSibling.style.display = "initial"
}

>Solution :

The problem is technically a logical error. Your HTML is different for page 1 and at least page 2.

Read the comments in the following code:

        <div class="formpage page1">
            <h1 class="display-1 align-items-center mb-4">Inscris-toi sur 
                <img src="../public/img/logo-gozpeak.png" alt="Logo Go Zpeak !" width="auto" height="60" class="d-inline-block align-text-top">
            </h1>
            <div class="form-floating mb-3">
                {{form_widget(userform.email, {'attr' : {'placeholder' : 'Mon adresse e-mail', 'class' : 'form-control'}})}}
                {{form_label(userform.email, 'Mon adresse e-mail', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.password.first, {'attr' : {'placeholder' : 'Mon mot de passe', 'class' : 'form-control'}})}}
                {{form_label(userform.password.first, 'Mon mot de passe', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating">
                {{form_widget(userform.password.second, {'attr' : {'placeholder' : 'Confirmation de mon mot de passe', 'class' : 'form-control'}})}}
                {{form_label(userform.password.second, 'Confirmation de mon mot de passe', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-checkbox">
                {{form_widget(userform.roles)}}
                <span class="checkbox"></span>
                <span class="checkmark"></span>
            </div>

            <!-- This isn't enclosed inside an element, hence its parent is the .formpage element above -->
            <button type="button" class="next btn btn-lg btn-outline-primary mt-4 d-flex mx-auto">Je m'inscris</button>
        </div>
        <div class="formpage page2">
            <h1 class="display-1 align-items-center mb-4">Pour savoir qui tu es.</h1>
            <div class="form-floating mb-3">
                {{form_widget(userform.gender, {'attr' : {'placeholder' : 'Es-tu un homme ou une femme ?', 'class' : 'form-control'}})}}
                {{form_label(userform.gender, 'Es-tu un homme ou une femme ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.firstname, {'attr' : {'placeholder' : 'Quel est ton prénom ?', 'class' : 'form-control'}})}}
                {{form_label(userform.firstname, 'Quel est ton prénom ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                {{form_widget(userform.lastname, {'attr' : {'placeholder' : 'Quel est ton nom de famille ?', 'class' : 'form-control'}})}}
                {{form_label(userform.lastname, 'Quel est ton nom de famille ?', {'label_attr' : {'class' : 'label'}})}}
            </div>
            <div class="form-floating mb-3">
                <p>Quelle est ta date de naissance ?</p>
                {{form_widget(userform.birthdate, {'select' : {'class' : 'form-select'}})}}
            </div>

            <!-- This is enclosed inside a div element, hence its parent is NOT the .formpage element above -->
            <div class="d-flex">
                <button type="button" class="prev btn btn-lg btn-outline-primary mt-4 d-flex me-auto">Précédent</button>
                <button type="button" class="next btn btn-lg btn-outline-primary mt-4 d-flex ms-auto">Suivant</button>
            </div>
        </div>...

Now one straightforward solution is to encapsulate the button on the first page around a div as well.

Leave a Reply