Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

NaderHamid9's avatar

Livewire Multistep form with JS Signature Pad

Hello, I'm building a KYC system that has multiple steps for the customer's info I'm using vildanbina/livewire-wizard for the multi step form it's working fine but on the last step I have created a javascript signature pad that allows the user to draw their signature and then stores it as a base64 the problem is that when I move through steps the javascript code of the signature pad doesn't work ( the user can't draw ) but when I reach the step of the signature and refresh the page the javascript code works and the user is able to sign

this is the function called on livewire component when I move thro steps

public function setStep($step): void { $this->callHook('beforeSetStep', $this->activeStep, $step);

    if ($this->hasPrevStep($step)) {
        $this->stepsValidation($this->prevStep($step));
    }

    $this->getCurrentStep()->callHook('onStepOut');

    $this->activeStep = $step;

    $this->getCurrentStep()->callHook('onStepIn');

    $this->callHook('afterSetStep', $this->activeStep, $step);
}

and this is the button of each step

<x-button.circle :positive="$stepIsGreaterOrEqualThan && !$isFailedStep" :negative="$isFailedStep" wire:click="setStep({{ $stepInstance->getOrder() }})" icon="{{ $stepInstance->icon() }}" />

the is the signaure pad view

                        <div class="m-signature-pad--body">
                            <canvas style="border: 2px dashed #ccc"></canvas>
                        </div>

                        <div class="m-signature-pad--footer">
                            <button type="button" data-action="clear" id="clear-btn" class="text-white bg-gray-800 hover:bg-gray-900 focus:outline-none focus:ring-4 focus:ring-gray-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700 dark:border-gray-700">مسح</button>

                            <button type="button" data-action="save" id="save-btn" class="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800">حفظ التوقيع</button>

                        </div>
                    </div>                      

                </div>

and finnaly this is the signature pad javascript

        // Wrap your JavaScript code inside a function to initialize the signature pad
        var wrapper = document.getElementById("signature-pad"),
            clearButton = wrapper.querySelector("[data-action=clear]"),
            saveButton = wrapper.querySelector("[data-action=save]"),
            canvas = wrapper.querySelector("canvas"),
            signaturePad;

        // Adjust canvas coordinate space taking into account pixel ratio,
        // to make it look crisp on mobile devices.
        // This also causes canvas to be cleared.
        function resizeCanvas() {
            var ratio =  window.devicePixelRatio || 1;
            canvas.width = canvas.offsetWidth * ratio;
            canvas.height = canvas.offsetHeight * ratio;
            canvas.getContext("2d").scale(ratio, ratio);
        }

        resizeCanvas();

        signaturePad = new SignaturePad(canvas);

        clearButton.addEventListener("click", function(event) {
            signaturePad.clear();
            $("#save-btn").prop("disabled", false);
            $("#save-btn").attr("class", "focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800");
            $("#img-data").val('');
        });

        saveButton.addEventListener("click", function(event) {
            event.preventDefault();

            if (signaturePad.isEmpty()) {
                alert("Please provide a signature first.");
            } else {
                var dataUrl = signaturePad.toDataURL();
                var image_data = dataUrl.replace(/^data:image\/(png|jpg);base64,/, "");

                // Set the value of the input field with id 'img-data' to the image_data
                $("#img-data").val(image_data);

                // Check if img-data is not null
                if ($("#img-data").val() != null) {
                    // Disable the button with id save-btn
                    $("#save-btn").prop("disabled", true);
                    $("#save-btn").attr("class", "py-2.5 px-5 me-2 mb-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700");

                } else {
                    // Enable the button with id save-btn
                    $("#save-btn").prop("disabled", false);
                }

                $.ajax({
                    url: '/save-signature',
                    type: 'POST',
                    data: {
                        image_data: image_data,
                    },
                }).done(function() {
                    //
                });
            }
        })
0 likes
0 replies

Please or to participate in this conversation.