Skip to content

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wizard plugin

Plugin that allows you to easily implement and configure a wizard system of steps with forms and validations to Winter CMS

wizard_example

Installation

composer require zimudec/wn-wizard-plugin

Usage example

Create a new page and add the "wizard" component. You must configure the url to admit an optional parameter "/:step?", Configure the wizard steps, functions for ajax and the views of each step. Here is a complete example of a page with the implementation and explanatory comments. It can be used as a starting point:

title = "Wizard Example"
url = "/wizard-example/:step?"
layout = "default"
is_hidden = 0

[wizard]
==
<?
function onInit()
{
  // Register and configure list of steps that the wizard component will use
  $this->wizard->steps = [

    // Each of the steps allows you to configure a list of form validations.
    // Once successfully validated, wizard will allow you to go to the next step.
    // The validations will be called from the related ajax request.
    ['step' => 'step1', 'name' => 'Step 1', 'forms' => [
      'onStep1' => [
        'validation' => ['field1' => 'required', 'field2' => 'required'],
        'extra_validation' => function($validator, $fields, $prevValidationsData) {
          // Extra validations
          $errors = $validator->errors();

          // You can optionally avoid performing the extra validations, 
          // if the previous validations are not fulfilled
          if(!$errors->any()){

            // Extra validations that are complex to perform in native array of laravel validations
            if($fields['field1'] != 'hello'){
              $errors->add('field1', 'The value of this field must be "hello"');
            }

            // Return data from here, allows you to use it in any subsequent step
            // For example: this allows you to validate by consulting a data in the database,
            // and reuse it in subsequent steps without having to consult it again
            // This data remains in session during all the steps, until it is revalidated
            return [
              'user' => ['id' => 1, 'names' => 'User', 'lastname' => 'my lastnames'],
            ];
          }
        }
      ]
    ]],
    // By default, when entering a page, the wizard does not validate the previous steps.
    // The "validatePrevSteps" field allows forcing the revalidation of all the previous steps.
    // This is useful when you need to update the data obtained from extra validations.
    ['step' => 'step2', 'name' => 'Step 2', 'validatePrevSteps' => true],
    ['step' => 'step3', 'name' => 'Step 3', 'forms' => [
      'onStep3' => [
        'validation' => ['select' => 'required'],
        'validation_messages' => [
          'select.required' => 'You must choose a value for :attribute field!'
        ],
        'extra_validation' => function($validator, $fields, $prevValidationsData){
        }
      ]
    ]],
    ['step' => 'step4', 'name' => 'Step 4'],
  ];
  
}

function onEnd()
{
  // To include this script, add the tag {% put scripts%} {% endput%} after jquery
  // This script shows and hides errors received from the server. Use bootstrap 4.x classes
  $this->addJs('/plugins/zimudec/wizard/assets/js/wizard.js');

  $wizard = $this['wizard'];

  if($wizard['stepCurrent'] == 'step1'){
    // This only runs when opening the page. At this point, no validations are performed
    $this['example_data'] = 'This is the step 1';
  } 
  elseif( $wizard['stepCurrent'] == 'step2' ){
    // You can get data received from the extra validations, and transfer it to the view
    $this['user'] = $wizard['prevValidationsData']['user'];

    // You can get the values of the fields that have been filled in previous steps
    $this['field2'] = $wizard['fields']['field2'];
    $this['field3'] = $wizard['fields']['field3'];
  }
  elseif( $wizard['stepCurrent'] == 'step3' ){
    $this['selectData'] = [
      ['id' => 1, 'name' => 'Name 1'],
      ['id' => 2, 'name' => 'Name 2'],
      ['id' => 3, 'name' => 'Name 3'],
    ];
  }

  // Set page title
  $this->page->title = $this->page->title . ' - '. $wizard['stepCurrentName'];
}

function onStep1()
{
  // When submitting the form in step1, this function will be executed and the extra validations and validations will be performed
  $data = $this->wizard->formsValidate();

  // Here you can perform any procedure before redirecting.
  // This procedure will only be done 1 time when submitting the form.
  // ...

  // Here the rediction will be made to the next step
  return redirect($data['stepNext']);
}

function onStep2()
{
  $data = $this->wizard->formsValidate();
  return redirect($data['stepNext']);
}

function onStep3()
{
  // By default, only the fields of the current form are validated, and not the previous steps.
  // When adding true as a parameter to the function,
  // will force validation of all previous steps, in addition to the current one.
  // This is useful for committing all the wizard data before doing something important, 
  // like inserting data into the database.
  $data = $this->wizard->formsValidate(true);
  return redirect($data['stepNext']);
}
?>
==
<section>
  {% partial '@nav_header.htm' title=(this.page.title) %}

  {% if wizard.stepCurrent == 'step1' %}

  <div class="text-center">{{ example_data }}</div>
  <form class="mx-auto" style="max-width: 400px;" data-request="onStep1" data-request-validate>
    {{ form_token() }}

    {% partial '@input_text.htm' label="Field 1 *" name="field1" %}
    {% partial '@input_text.htm' label="Field 2 *" name="field2" %}
    {% partial '@input_text.htm' label="Field 3" name="field3" %}

    {% partial '@nav_buttons.htm' %}
  </form>

  {% elseif wizard.stepCurrent == 'step2' %}

  {% partial '@header.htm' text=('Welcome ' ~ user.names) subtitle='This step does not require entering fields' %}
  <form class="mx-auto" style="max-width: 400px;" data-request="onStep2" data-request-validate>
    {{ form_token() }}
    {% partial '@input_text.htm' label="Field 2" value=(field2) readonly=true %}
    {% partial '@input_text.htm' label="Field 3" value=(field3) readonly=true %}
    {% partial '@nav_buttons.htm' %}
  </form>

  {% elseif wizard.stepCurrent == 'step3' %}

  {% partial '@header.htm' subtitle='This is the last step before finish the wizard' %}
  <form class="mx-auto" style="max-width: 400px;" data-request="onStep3" data-request-validate>
    {{ form_token() }}

    {% partial '@input_select.htm' label="Select *" name="select" items=(selectData)  %}
    {% partial '@nav_buttons.htm' %}
  </form>

  {% elseif wizard.stepCurrent == 'step4' %}

  <div class="mt-3 text-center">Wizard Finished. The wizard session was deleted. If you reload the page, it will go back to step1.</div>
  <hr >
  {% partial '@nav_buttons.htm' %}

  {% endif %}
</section>

Using translated customs error messages

When you define your steps, it is also possible to define custom error messages associated with your validations by using validation_messages key.

$this->wizard->steps = [
  [
    'step' => 'step1',
    'name' => 'Step 1',
    'forms' => [
      'onStep1' => [
        'validation' => ['myField' => 'required'],
        'validation_messages' => [
          'myField.required' => 'You must choose a value for :attribute field!'
        ],
        'extra_validation' => function($validator, $fields, $prevValidationsData){}
      ]
    ]
  ],
  // ...
]

If you need to get these messages in different languages, you can use per-language files.
For example, you can create a file per language, in the dedicated directory ./lang/[language key]/zimudec/wizard/validations.php, containing the messages définitions.

// ./lang/en/zimudec/wizard/validations.php
<?php

return [
    'myField_required' => 'You must choose a value for :attribute field!',
];

// ./lang/fr/zimudec/wizard/validations.php
<?php

return [
    'myField_required' => 'Vous devez choisir une valeur pour le champ :attribute !',
];

And then reference those definitions in your steps :

  'validation_messages' => [
    'myField.required' => Lang::get('zimudec.wizard::validations.myField_required')
  ],

If you need to learn more about validation in Winter CMS, check the documentation for Services/validation.

About

Plugin for Winter CMS that allows you to easily implement and configure a wizard system of steps with forms and validations

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages