Feedback Laraform is now in maintenance mode. Read more on our GitHub.

Extending On Frontend

#Extending Schema

In most of the cases you'll have everything defined on the backend but sometimes you still need to add certain features to elements on the frontend. Luckily everything you define on the frontend schema property will be merged with what you have on the backend.

Let's see an example. Create App\Forms\RegistrationForm.php:

<?php

namespace App\Forms;

class RegistrationForm extends \Laraform
{
  public function schema() {
    return [
      'name' => [
        'type' => 'text',
        'label' => 'Name'
      ],
      'email' => [
        'type' => 'text',
        'label' => 'Email'
      ],
      'country' => [
        'type' => 'select',
        'label' => 'Country'
      ],
      // ...
    ];
  }
}

As you can see we haven't defined items for country select - this is because we're planning to have them loaded asynchronously.

We're going to use a similar solution than select element's Async Options example to add async loading for our country field.

First, let's create a resources/js/forms/RegistrationForm.vue:

<script>
  export default {
    mixins: [Laraform],
    data() {
      return {
        schema: {
          country: {
            items: {},
            search: true,
            slots: {
              noOptions: Vue.extend({
                props: ['el$'],
                template: `<span>Start typing...</span>`
              })
            },
            options: {
              'internal-search': false
            },
            created() {
              this.loading = true

              this.on('searchChange', (searchQuery) => {
                axios.get(`/countries?q=${this.select$.search}`).then((response) => {
                  this.loading = false

                  this.items = response.data
                })
              })
            }
          }
        }
      }
    }
  }
</script>

Notice that we're not defining any of the existing options of country element like type or label because those are already provided by the backend and will be merged.

Next register the component in your app.js or main JS file and add that as a component to the backend form:

class RegistrationForm extends \Laraform
{
  public $component = 'registration-form';

  // ...
}

There you go! Now if you render the form you'll notice that the options of select have been merged and you have async loading for select items.

#Extending Buttons

Buttons are quite familiar to elements and sometimes we need to add some frontend featues to buttons which are already existing on the backend.

Let's see an example for that too. Having the same form as previously we're adding some buttons to it:

<?php

namespace App\Forms;

class RegistrationForm extends \Laraform
{
  public $component = 'registration-form';

  public function schema() {
    // ...
  }

  public function buttons() {
    return [
      [
        'label' => 'Submit'
      ],
      [
        'label' => 'Reset',
        'prevent' => true
      ]
    ];
  }
}

By default each button will submit the form unless it has the prevent option set to true. So we're good with Submit as it will submit the form, but Reset will do nothing at all. Let's change that!

In our previously created RegistrationForm.vue we're going to add some definition for the Reset button:

<script>
  export default {
    mixins: [Laraform],
    data() {
      return {
        schema: {
          // ...
        },
        buttons: [
          // Submit button - nothing added
          {},

          // Reset button
          {
            onClick() {
              this.form$.reset()
            }
          }
        ]
      }
    }
  }
</script>

That's it! The onClick option will be merged with the button's other options from the backend and now it will actually reset the form when clicked.

#Extending Other Properties

The two main properties were discussed in the last two sections, but there are couple of other properties Laraform is using to operate.

The rule of thumb is that everything you define on the frontend will overwrite what you have on the backend. This is of course not true for everything as we've already seen previously. The following properties are being merged instead of being replaced: