Submission

#Submitting Data

Laraform's .submit() methods initiates the form submission process. By default if the form's template is not overridden this method is called when the form submits.

#Submission Process

When .submit() method is called the form first checks it's disabled property. If true it aborts the submission instantly, otherwise it starts the submission process.

By disabled we mean that the form has either invalid fields, async validation in progress or currently submitting a previous request. Check out States section to learn more about them.

As a first step the form fires it's submit event. If a listener for this event returns false the form submission will be cancelled.

Next the form validates all the elements which weren't validated before. 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 will abort otherwise will move forward.

Once it passed it's prerequisites the form will submit the HTTP request to the endpoint defined as endpoint option or set globally in Configuration.

Let's take a look at a complete example of the submission process:

// State Properties:

        
          
<script>
  export default {
    mixins: [Laraform],
    data: () => ({
      endpoint: '/sending-request-form',
      schema: {
        name: {
          type: 'text',
          label: 'Name',
          rules: 'required'
        },
        url: {
          type: 'text',
          label: 'Name',
          debounce: 300,
          // this is an async rule
          rules: 'active_url'
        },
      },
      buttons: [
        {
          label: 'Submit',
          class: 'btn-primary',
          disabled() {
            // this.form$ is the root Laraform component
            return this.form$.disabled
          }
        },{
          label: 'Reset',
          class: 'btn-light',
          prevent: true,
          onClick() {
            this.form$.reset()
          } 
        }
      ]
    }),
    created() {
      this.on('submit', () => {
        alert('Submission process started')
      })
    }
  }
</script>
        

#Request Object

Laraform uses axios to handle it's HTTP requests. The requests are sent as POST along with custom headers and the form's data being converted to FormData object.

When Laraform initiates a submission request it sends an object containing two properties: key and data.

  axios.post(this.endpoint, {
    key: this.key,
    data: this.filtered
  }).//...

'key' Property

The key property is equivalent to the form's key property and it's main purpose to identify a form in the backend.

Let's say we have a form schema defined in a backend class and passed to Laraform via it's :form property. Now, when the form submits the backend needs to know which form should be used, because otherwise it sees only a set of data - this is where key comes in.

'data' Property

The submission data property contains the form's filtered data property, which represents the set of data which should be submitted. The reason there is a filtered data property instead of just using data is because some elements might have submit set to false meaning they shouldn't be submitted or they can have conditions which are not met and therefore they shouldn't be treated as part of the form.

// Payload (submit first):

        
          
<script>
  export default {
    mixins: [Laraform],
    data: () => ({
      key: '81195339-8329-466d-8862-87ba7d139d10',
      endpoint: '/endpoint/to/process',
      schema: {
        name: {
          type: 'text',
          label: 'Name'
        },
        birthday: {
          type: 'object',
          label: 'Birthday',
          schema: {
            day: {
              type: 'text',
              placeholder: '30',
              columns: 4
            },
            month: {
              type: 'text',
              placeholder: '01',
              columns: 4
            },
            year: {
              type: 'text',
              placeholder: '1970',
              columns: 4
            }
          }
        }
      },
      buttons: [{
        label: 'Submit',
        class: 'btn-primary'
      }]
    })
  }
</script>
        

#Request Headers

You may specify custom headers to send along with the HTTP request. Headers can be set globally at Configuration.

const config = {
  headers: [
    {
      name: // header name
      value: // header value
    }
  ]
}

Laraform.config(config)

#CSRF Token

Here's a short note on CSRF tokens, because processing HTTP requests in certain frameworks, like Laravel might require them. Even Laravel's newer versions come with built-in axios headers, in some cases you might need to specify them on your own.

Here's an example of using CSRF token headers in Laravel:

const config = {
  headers: [
      {
          name: 'X-CSRF-TOKEN',
          value: document.head.querySelector('meta[name="csrf-token"]').content,
      }
  ],
}

Laraform.config(config)

#Response Object

After the submission request has been processed by the backend it returns with a response. To catch this response you can subscribe to either response, fail or success events. All of them receives a response object as the first parameter, which is the axios response object.

export default {
  mixins: [Laraform],
  // ...
  created() {
    this.on('response', (response) => {
      // the form has a response
    })

    this.on('success', (response) => {
      // the form has a response with success status
    })

    this.on('fail', (response) => {
      // the form has a response with fail status
    })
  }
}

#Response Data

The response object has a data property which contains the response data of the backend. By default Laraform relies on this data to perform some actions, like firing fail and success events or updating form data. In the followings you will see what Laraform will do by default if you provide certain properties in the response object.

export default {
  mixins: [Laraform],
  // ...
  created() {
    this.on('response', (response) => {
      // this is the data sent by the backend
      var data = response.data
    })
  }
}

Response Status

If status property is present in the response object it will fire the event with the same name. By default this is expected to be either success or fail to fire the related event. You can achieve the same like that:

export default {
  mixins: [Laraform],
  // ...
  created() {
    this.on('response', (response) => {
      if (response.data.status) {
        this.fire(data.status, response)
      }
    })
  }
}

When using Laraform default backend library response data is configured this way.

Response Payload

By default payload property should be used to send any concrete data to be processed by the form when handling the response.

If updates is present in payload, Laraform will update the form data with it's content. You could do the same manually like that:

export default {
  mixins: [Laraform],
  // ...
  created() {
    this.on('success', (response) => {
      if (response.data.payload && response.data.payload.updates) {
        this.update(data.payload.updates)
      }
    })
  }
}

#Response Messages

Laraform does not manage response messages, like showing a successful registration feedback or displaying additional errors from the backend as they would be out of the scope of managing forms. Luckily, you can implement your own custom solution quite easily.

export default {
  mixins: [Laraform],
  // ...
  created() {
    this.on('success', (response) => {
      this.notify(response.message, 'success')
    })

    this.on('fail', (response) => {
      this.notify(response.message, 'error')
    })
  }
}

Please note that .notify() method is not provided by Laraform, but you can choose from couple of solutions out there.

#States

State properties are properties that represent a special state of form which usually prevents the form from submitting. You can see them in action at the end of Submission Process section.

#Invalid

If the form has any invalid elements, meaning elements which failed their validation rules, the form will also have invalid set to true.

#Busy

In such cases when an element has async validation rule the form will wait and only proceeds once all of them finished. During this the form's busy property is set to true, which signs that the form has some kind of async process in progress which blocks the submission. When all async processes finished and the form has no invalid fields the actual submission will start, otherwise it will abort.

#Submitting

When a form sends the submission HTTP request it will change it's submitting property to true, which signs that there is an ongoing submission.

#Disabled

If either invalid, busy or submitting is true, the form's disabled property will be set to true which instantly aborts .submit() if called. Buttons also have a disabled property which accepts a function and expected to return a boolean value which sets the button's disabled state.

#Custom Submission Logic

In case you want to implement your own submission process or use a different HTTP library for example you can do so easily by overriding the form's .submit() method.

export default {
  mixins: [Laraform],
  // ...
  methods: {
    submit() {
      // implement custom solution
    }
  }
}

Checkout Laraform API Reference for methods and properties that might come handy when dealing with different aspects of submitting data. As for new see this complete example of implenenting Vue Resource as a HTTP handler instead of axios:

import VueResource from 'vue-resource'

Vue.use(VueResource)

export default {
  mixins: [Laraform],
  // ...
  methods: {
    submit() {
      // don't let the user submit if the form is disabled
      if (this.disabled) {
        return
      }

      // firing submit event and preventing further 
      // execution if the event returns `false`
      if (this.fire('submit') === false) {
        return
      }

      // start the validation of all elements
      this.validate()

      // wait for all async validations to 
      // complete then send the form data
      this.proceed(() => {
        var data = this.formData({
          key: this.key,
          data: this.filtered
        })

        this.$http.post(this.endpoint, data).then((response) => {
          // handling response
        })
      })
    }
  }
}

#Submit Event

When a form is submitted a submit event is fired. If the listener you have subscribed for the event returns false it prevents the form submission before validation takes place.

export default {
  mixins: [Laraform],
  // ...
  created() {
    this.on('submit', () => {
      // the form has been submitted

      // prevent further execution
      return false
    })
  }
}