Wizard & Tabs

#Wizard

Wizard breaks down the form into different steps. To create a wizard simply add wizard object to your form's .data():

export default {
  mixins: [Laraform],
  data: () => ({
    wizard: {
      // steps
    },
    schema: {
      // schema
    }
  })
}

The wizard property accepts an object containing steps:

export default {
  mixins: [Laraform],
  data: () => ({
    wizard: {
      first_step: {
        // first step
      },
      second_step: {
        // second step
      },
    },
    schema: {
      // schema
    }
  })
}

Step object accept a label property which sets the label of the step when shown above the form, and elements which is an array of element names to include in the step.

Optionally you can define labels which is an object that can have a previous, next and finish property representing the labels of the Previous, Next and Finish buttons. If labels are not provided they will be retrieved from locale file.

Also optionally you can disable previous and next buttons by using buttons property.

export default {
  mixins: [Laraform],
  data: () => ({
    wizard: {
      personal_details: {
        label: 'Personal details',
        elements: ['firstname', 'lastname'],
        buttons: {
          previous: false
        }
      },
      contact_details: {
        label: 'Contact details',
        elements: ['email', 'phone'],
        labels: {
          previous: 'Go back',
          next: 'Continue'
        }
      },
    },
    schema: {
      firstname: {
        type: 'text',
        label: 'First name'
      },
      lastname: {
        type: 'text',
        label: 'Last name'
      },
      email: {
        type: 'text',
        label: 'Email'
      },
      phone: {
        type: 'text',
        label: 'Phone'
      },
    }
  })
}

In fact there's a third conditions property that can make the form step conditional. It's already covered in Conditions chapter so we will not get into it this time.

It's time for a showcase, so let's see how our example above looks like in real life:

          
<script>
  export default {
    mixins: [Laraform],
    data: () => ({
      wizard: {
        personal_details: {
          label: 'Personal details',
          elements: ['firstname', 'lastname'],
          buttons: {
            previous: false
          }
        },
        contact_details: {
          label: 'Contact details',
          elements: ['email', 'phone'],
          labels: {
            previous: 'Go back',
            next: 'Continue'
          }
        },
        job_history: {
          label: 'Job history',
          elements: ['previous_jobs']
        },
      },
      schema: {
        firstname: {
          type: 'text',
          label: 'First name'
        },
        lastname: {
          type: 'text',
          label: 'Last name'
        },
        email: {
          type: 'text',
          label: 'Email'
        },
        phone: {
          type: 'text',
          label: 'Phone'
        },
        previous_jobs: {
          type: 'list',
          label: 'Previous jobs',
          element: {
            type: 'text',
            placeholder: 'Job'
          }
        },
      }
    })
  }
</script>
        

Note how Next, Previous and on the last step Finish buttons appear without defining any buttons. This is because these buttons implement a fairly complex logic to deal with validation, submission, etc. which might be too much to understand for a newcomer. Of course these buttons can be disabled by setting wizardControls to false on the form and implement you own solution.

Next Button

Next button's obvious goal is to proceed to the next step. The user however can be limited to do so if the current step has any invalid fields.

There is an option called validateOn which accepts 'step' as a possible value and it can be defined either at the form instance or globally in configuration. If 'step' is presented in this variable the next button will prevent the user to proceed to the next step, if the current one has any invalid fields.

Previous Button

By pressing Previous button the form steps back one step. By default it's disabled if the user is on the first step.

Finish Button

When the user arrives to the last step the Finish button will appear instead of Next. By clicking it, all the elements which weren't validated before are now being validated. In case of an async validation the form will wait for them to finish and determines if it has any invalid elements. If it does the submission aborts and the user is redirected to the first step which contains error. Otherwise it invokes form's .submit() method and starts the submission process.

#Conditional Steps

Conditions can be binded to wizard steps just like to any element, via it's conditions property. Each step is represented by an object, where you place the step's properties like label or elements, and this is where conditions is placed too.

wizard: {
  first_step: {
    label: 'First Step',
    elements: ['id', 'name'],
    conditions: [
      // ...
    ]
  }
}

The conditions property is an array and it's elements can be arrays, functions or strings just as like anywhere else.

The following example demonstrates how Company details can be optional during a registration where the user can check a Register as company checkbox in order to fill out company information:

// `filtered` form data:

        
          
<script>
  export default {
    mixins: [Laraform],
    data: () => ({

      // Wizard steps definition
      wizard: {
        personal_details: {
          label: 'Personal details',
          elements: ['name', 'register_company']
        },
        company_details: {
          label: 'Company details',
          elements: ['company_name', 'company_address'],

          // Company details conditions
          conditions: [
            ['register_company', true]
          ]
        },
        account_details: {
          label: 'Account details',
          elements: ['email', 'password'],
        }
      },

      // Form elements
      schema: {
        name: {
          type: 'text',
          label: 'Name',
          rules: 'required'
        },
        register_company: {
          type: 'checkbox',
          text: 'Register as company'
        },
        company_name: {
          type: 'text',
          label: 'Company name',
        },
        company_address: {
          type: 'text',
          label: 'Company address',
        },
        email: {
          type: 'text',
          label: 'Email address'
        },
        password: {
          type: 'text',
          label: 'Password'
        },
      },
    })
  }
</script>
        

Note how company_name and company_address are being excluded from filtered data when the Company details step is hidden.

#Tabs

Tabs and wizard are fairly similar in most of their aspects except that Tabs do not have controls and neither they are disabled before the user fills out the previous one.

#Creating Tabs

Tabs and wizard are also configured the same way, so instead of repeating ourselves let's just see the same example but using tabs instead of a wizard:

          
<script>
  export default {
    mixins: [Laraform],
    data: () => ({
      tabs: {
        personal_details: {
          label: 'Personal details',
          elements: ['firstname', 'lastname']
        },
        contact_details: {
          label: 'Contact details',
          elements: ['email', 'phone']
        },
      },
      schema: {
        firstname: {
          type: 'text',
          label: 'First name'
        },
        lastname: {
          type: 'text',
          label: 'Last name'
        },
        email: {
          type: 'text',
          label: 'Email'
        },
        phone: {
          type: 'text',
          label: 'Phone'
        },
      }
    })
  }
</script>
        

#Conditional Tabs

Similarly to wizard steps, tabs can also have conditions. They are defined exactly the same way as wizard step conditions: via conditions property.

tabs: {
  first_tab: {
    label: 'First Tab',
    elements: ['id', 'name'],
    conditions: [
      // ...
    ]
  }
}

The conditions property is an array and it's elements can be arrays, functions or strings.

In the following see the example of a product's form, which optionally has Product gallery if Has gallery checkbox is checked:

// `filtered` form data:

        
          
<script>
  export default {
    mixins: [Laraform],
    data: () => ({

      // Tabs steps definition
      tabs: {
        product_details: {
          label: 'Product details',
          elements: ['name', 'description', 'has_gallery']
        },
        product_gallery: {
          label: 'Product gallery',
          elements: ['gallery'],

          // Product gallery conditions
          conditions: [
            ['has_gallery', true]
          ]
        }
      },

      // Form elements
      schema: {
        name: {
          type: 'text',
          label: 'Product name'
        },
        description: {
          type: 'text',
          label: 'Product description'
        },
        has_gallery: {
          type: 'checkbox',
          text: 'Has gallery'
        },
        gallery: {
          type: 'gallery',
          label: 'Gallery'
        }
      },
      buttons: [{
        label: 'Submit',
        class: 'btn-primary',
        disabled() {
          return this.form$.disabled
        }
      }]
    })
  }
</script>
        

Note how gallery is being excluded from filtered data when the Product gallery tab is hidden.