Custom Element

#Creating Custom Elements

#Using Mixins

To create a custom element you need to be aligned with API methods and properties an element requires. Therefore it's not advisable to create an element completely from scratch, rather it should use some of Laraform's mixins. Let's see an example of creating a custom TextElement:

// ./path/to/custom/TextElement.vue

<template>
  <div>
    <input type="text" v-model="model" />
  </div>
</template>

<script>
  import BaseElement from '@laraform/laraform/src/mixins/BaseElement'
  import BaseValidation from '@laraform/laraform/src/mixins/BaseValidation'

  export default {
    name: 'TextElement',
    mixins: [BaseElement, BaseValidation]
  }
</script>

As you can see it uses BaseElement and BaseValidation mixins which is what you really need to create a basic element. It will have access to all the basic methods and properties an element offers and you can use them in your element like we are using model as v-model.

Laraform offers a few different mixins, but we are not going to go through all of them in details right now. Our purpose here is to give you the idea of creating custom elements, but if you decide to dig deeper, make sure to check out laraform/src/mixins directory for more.

#Extending Elements

An other, probably more convenient way to create or replace elements is to extend an existing one. Let's see how we can do that with a TextElement:

// ./path/to/custom/TextElement.vue

<template>
  <div>
    <input type="text" v-model="model" />
  </div>
</template>

<script>
  import TextElement from '@laraform/laraform/src/components/elements/TextElement'

  export default {
    name: 'TextElement',
    mixins: [TextElement]
  }
</script>

That's it! Now you have a custom TextElement and you can define custom properties, methods, lifecycle hooks, etc.

#Using Custom Elements

You can use your custom elements in different ways. Let's see what are those!

#Via 'component' Property

Elements have an option called component which allows you to replace the element's component completely. This way you can define you custom component for any element type and use it by passing over as the component property. Let's see that in action:

export default {
  mixins: [Laraform],
  data: () => ({
    schema: {
      code: {
        type: 'checkbox',
        label: 'Clickable label on the left',
        component: Vue.extend({
          props: ['schema', 'name'],
          template: `
            <div>
              <label>
                {{ schema.label }} <input type="checkbox" />
              </label>
            </div>
          `
        })
      }
    }
  })
}

Using Vue.extend() you can create a component on to fly and use it as an element. Of course in this case you have to take care of creating all the API methods and properties so it's more advisable to follow the steps from above.

If you have created a Single File Component by extending mixins or an existing element then you can pass it to the component option easily:

// SFC for custom checkbox
// ./path/to/custom/CheckboxElement.vue

<template>
  <div>
    <label>
      {{ schema.label }} <input type="checkbox" />
    </label>
  </div>
</template>

<script>
  import CheckboxElement from '@laraform/laraform/src/components/elements/CheckboxElement'

  export default {
    name: 'MyCheckboxElement',
    mixins: [CheckboxElement]
  }
</script>
// ./path/to/MyForm.vue

import MyCheckboxElement from './path/to/custom/MyCheckboxElement.vue'

export default {
  mixins: [Laraform],
  data: () => ({
    schema: {
      code: {
        type: 'checkbox',
        label: 'Clickable label on the left',
        component: MyCheckboxElement
      }
    }
  })
}

And voila! Now you checkbox element will be replaced by the one you created.

#Registering Globally

In case you've created an element that you want to use more frequently you can register them globally to avoid local imports. To do so simply call .element() method before installing Laraform:


import Vue from 'vue'
import Laraform from '@laraform/laraform'

import MyCheckboxElement from './path/to/custom/MyCheckboxElement.vue'

Laraform.element('checkbox', MyCheckboxElement)

Vue.use(Laraform)

const app = new Vue({
  el: '#app'
})

By registering your custom component globally, anytime you use a checkbox type element, that one will be used instead of Laraform's default element. Of course you can not only replace element this way, but register your custom ones.

#Using 'static' Component

One last way of using custom components is a bit different idea than the previous ones, as it does not actually replace the components, but rather gives you the opportunity to create components within components. Let's see what we mean by that:

export default {
  mixins: [Laraform],
  data: () => ({
    schema: {
      custom_field: {
        type: 'static',
        label: 'Custom Element',
        foo: 'bar',
        content: Vue.extend({
          props: ['el$'],
          template: `
            <div>I'm a component and can access element API via el$: {{ el$.foo }}</div>
          `
        })
      }
    }
  })
}

This will render a casual element in the form, with a custom component in it's field part. As you can see a property called el$ is being passed over to the component, so this way you can access it's methods and properties. Of course you are free to use Single File Components instead of defining the component on the fly with Vue.extend().