Skip to content

VueForms (StatCan.OrchardCore.VueForms)

The VueForms module aims to simplify the creation of client side forms in OrchardCore.

Content definitions

VueForm

The VueForm content type is used to create forms that use VueJs and VeeValidate client side libraries. The form submission is handled via an ajax call to a generic controller that returns json to the client for seamless server side validation.

VueForm Part

Field Definition
Disabled If disabled, the DisabledHtml field value will be displayed instead of the form
RenderAs Render the Form as a Vue Component, a Vue App or Vuetify app
DisabledHtml Html displayed when the form is disabled.
SuccessMessage The success message returned to the client when the form is valid and no redirect is specified after submission. With Liquid support.
Template The component template. With Liquid support.
Debug mode Enables debug mode on the form.

Note about RenderAs: When rendering the Form as a VueComponent, you need to define a Zone in your layout called DynamicComponentZone. This zone must be rendered anywhere before the FootScript resource zone. This is required because the div that defines the VueForm component needs to be defined outside of the Vue App. Please look at our open source VuetifyTheme layout for an example.

{% render_section "DynamicComponentZone", required: false %}
{% resources type: "FootScript" %}

Template

The template of the vue component

Example:

<v-container >
  <v-card-text>
    <v-row justify="center">
      <v-col cols="8">
        <validation-provider name="{{ "nameLabel" | localize | downcase }}" rules="required" v-slot="{ errors }">
          <v-text-field v-model="name" :error-messages="errors" filled="filled" label="{{ "nameLabel" | localize }}"></v-text-field>
        </validation-provider>
      </v-col>
      <v-col cols="8">
        <validation-provider name="{{ "emailLabel" | localize | downcase }}" rules="required|email" v-slot="{ errors }">
          <v-text-field v-model="email" :error-messages="errors" filled="filled" label="{{ "emailLabel" | localize }}"></v-text-field>
        </validation-provider>
      </v-col>
      <v-col cols="8">
        <validation-provider name="{{ "messageLabel" | localize | downcase }}" rules="required" v-slot="{ errors }">
          <v-textarea v-model="message" :error-messages="errors" counter="true" filled="filled" label="{{ "messageLabel" | localize }}" rows="5">
          </v-textarea>
        </validation-provider>
      </v-col>
      <v-col cols="8">
        <v-alert type="success" v-if="form.successMessage">
          {% raw %}{{ form.successMessage }}{% endraw %}
        </v-alert>
        <v-alert type="error" v-if="form.errorMessage">
          {% raw %}{{ form.errorMessage }}{% endraw %}
        </v-alert>
      </v-col>
      <v-col cols="8">
        <v-btn type="submit" depressed block @click="formHandleSubmit" :disabled="form.submitting">{{ "submitLabel" | localize }}</v-btn>
      </v-col>
    </v-row>
  </v-card-text>
</v-container>
Available Props

The VueForm component has some default properties and methods.

You can access these properties in your templates or in the component options object.

Name Definition
obs.* All props available on the v-slot of the ValidationObserver are available.
formReset A method that resets the form.* properties to the initial state. Does not reset your component's data. () => void
formHandleSubmit A method that calls the validate() method and then, if valid, sends an ajax request to our controller () => void
form.submitting Set to true when the form is being submitted.
form.submitSuccess Set to true when no redirect is specified and the submission was a success.
form.successMessage The success message returned from the server as specified in the VueForm
form.submitValidationError Set to true when a server validation error occus.
form.serverValidationMessage Array of errors set by the server with the addError('serverValidationMessage', 'Message') scripting method.
form.responseData The raw response data recieved from the server. Useful if you want to return additional data to the form via a workflow.
form.submitError Set to true when a server error, ajax error or unhandled error occurs.
form.serverErrorMessage An error message set with the ajax error status code and text. Only set when a server errors occur.

Debug mode

Debug mode is typically used when developping a form. Additional information is returned by the server and any data output by the debug() scripting method is also output and returned with the HttpResponse. This mode does not work when previewing the form.

VueFormScripts Part

Field Definition
ClientInit A client side script that is executed prior to instanciating the VueJs app.
ComponentOptions The VueJS component options object for your VueForm component.
OnValidation Server side validation script that allows us to validate the form.
OnSubmitted Server side script that runs if the form is valid

ClientInit script

The ClientInit script is executed client side prior to instanciating the form component. This script has access to the client's global scope variables.

This was added to support hooking into some global options for VeeValidate.

For example, setting the VeeValidate.setInteractionMode('passive') option or the Localization option.

VeeValidate.setInteractionMode("passive");

OnValidation script

The OnValidation script is used to specify the server side validation script. We are planning to implement components with integrated validation in the future. This module adds some scripting methods to facilitate handling form data and errors.

Here is an example OnValidation script that validates that the name is required.

Note: the first parameter of addError must be your input name that must also match the VeeValidate ValidationProvider name.

var data = requestFormAsJsonObject();

if (data.name == "") {
  addError("name", "The name is required");
}

All errors are also available to the client Vue component via the form.responseData.errors property

OnSubmitted script

The OnSubmitted script is executed after the OnValidation script, only if the form is valid. This is where you would typically create a contentItem from the form data or redirect the user to another page.

Here is an example OnSubmitted script that redirects the user to a success page after having created the PersonInfo content item.

var data = requestFormAsJsonObject();

createContentItem("PersonInfo", true, {
  PersonInfo: {
    Name: {
      Text: data.name
    },
    Email: {
      Text: data.email
    },
    Gender: {
      Text: data.gender
    }
  }
});
// redirects to the success page
httpRedirect("~/success");

Component Options object

This is where you write theVueJS component options object for the form component. At a minimum, you must define the data object. By default, the entire data object is serialized and sent to the server when the form is submitted.

{
  data: () => ({
    items: ["Female", "Male", "Other"],
    name: "",
    email: "",
    gender: undefined
  });
}

You can also overwrite the submitData() method to customize what is sent to the server. This can be very useful when your data object contains list of items for a dropdown.

{
  data: () => ({
    items: ["Female", "Male", "Other"],
    name: "",
    email: "",
    gender: undefined
  }),
  submitData() {
    return { name: this.name, email: this.email, gender: this.gender };
  },
}

Custom Form Components

The sections below decribes the custom form components provided by this module.

Multiselect components

The module exposes two multiselect components: multiselect-async and multiselect. These components are wrappers of the multiselect component from the vue-multiselect library. The api of the base vue-multiselect component can be found here.

multiselect-async component

The multiselect-async component allows async loading of options from an api.

Props Definition
value The holder of the selected options
api The url of the api that the options are coming from
success A boolean representing the validation result
error-messages Messages to show when validation fails

All the other props are the same as the base multiselect component.

multiselect component

The multiselect component provides a multiselect feature without async loading of options.

Props Definition
value The holder of the selected options
success A boolean representing the validation result
error-messages Messages to show when validation fails

All the other props are the same as the base multiselect component.

Bag component

The bag component provides a bag behaviour to the form. A bag is a collection of field groups. The bag component behaves similar to the BagPart in Orchard Core.

Props Definition
value The holder of the selected options over the entire bag
valueNames The name of the value object of each individual field in a field group
add-button-label The label of the add button
remove-button-label The label of the remove button
success A boolean representing the validation result.
errorMessages Messages to show when validation fails

Below is an example of the value object:

value: [{ field1: "field1Value", field2: "field2Value" }];

The general form of the value object is an array of objects. Each object represents a group of fields. Each proprety represents the value of a specific field.

The valueNames prop is a string array of the proprety name used in the field group objects in the value object. For example, the valueNames array corresponding to the value object given above is

valueNames: ["field1", "field2"];

Bag component example

Here is an example of using the bag component

<validation-provider name="Bag" rules="required" v-slot="{ errors, valid }">
  <bag
    v-model="bagValues"
    :valueNames="valueNames"
    :success="valid"
    :error-messages="errors"
    add-button-label="Add"
    remove-button-label="-"
  >
    <template #validations>
      <validation-provider
        rules="required"
        name="Field 1"
      ></validation-provider>
      <validation-provider
        rules="required"
        name="Field 2"
      ></validation-provider>
    </template>

    <template #components>
      <v-text-field filled="filled" label="label"> </v-text-field>
      <v-text-field filled="filled" label="label"> </v-text-field>
    </template>

    <template #title>
      <div class="text-h5 mb-5">
        Bag
      </div>
    </template>
  </bag>
</validation-provider>

The data object is:

{
    data: () => ({
        bagValues: [{ field1: "field1", field2: "field2" }],
        valueNames: ["field1", "field2"]
    })
}

The bag component can be wrapped in a validation-provider just like any other field components.

The bag component has three slots. The validations slots contains the validation-provider for each field in the field groups. The components slot contains the actual field components. The title slot contains components representing the title of the bag component.

The components in the validations and components slots are prototypes. For example, whenever the add button is clicked, the components defined in those two slots will be "instantiated".

Some notes on using the bag component

Components defined in the validations and components slots should not contain any children.

Ignore v-slot="{ errors, valid }" when defining validation-provider components in the validations slot because it is handled by the bag component.

Ignore v-model, :success, and :error-messages when defining components in the components slots because they are handled by the bag component.

Scripting

Please see the scripting documentation.

Workflow integration

Although this module does not require a workflow to handle the form submissions, we still provide a workflow hook to support performing some additional actions.

Please see the workflow documentation.

If you do use a workflow, you can use the addError("name", "message"); script to add form errors. You can also use the HttpRedirect or HttpResponse workflow tasks to redirect or return a custom set of data to the client. All data returned by the HttpResponse task is available via the form.responseData object. You should also be able to use the debug() scripting method to return debugging data to the client.

Localization (StatCan.OrchardCore.VueForms.Localized)

While you can use Orchard's LocalizationPart to localize your forms. We suggest you use the LocalizedText feature to implement i18n in your forms. This part is what we weld to your VueForm content type when you enable this feature.

The [locale] shortcode is also useful to use in your views to localize simple text fields.

Survey (StatCan.OrchardCore.VueForms.Survey)

Adds SurveyJS support to VueForms. This adds a part to the VueForm where you can specify the SurveyJS creator json object.

In the Template, simply write this to output a Survey that uses the SurveyJS json object

<survey :survey="survey"></survey>

To get the json output of the survey on your server side scripts, simply use the getSurveyData() method.

const surveyData = getSurveyData();
debug("surveyData", surveyData);

Examples

The following example forms are provided with the VueForms module as recipes:

  • Contact Form
  • UserProfile Form

UserProfile Form

This form allows you to edit a UserProfile Content Type with the CustomUserSettings stereotype. For this form to work, you must enable the Users Change Email feature along with allowing users to update their email in the settings.


Last update: November 8, 2021