Skip to main content

Creating a field

You can create a custom field either by extending another field, or create one from scratch. Fields consists of 4 vue templates: Filter.vue, Index.vue, Detail.vue and Field.vue

Getting started

Let's create a basic field from scratch.

Back-end

The component is the name of the Vue component:

class Example extends Field
{
public function component(): string
{
return 'Example';
}
}
caution

When you extend an existing Field like Select, and you need a custom component for your index, make sure to set:

public bool $rendersTextOnIndex = false;

For performance reasons, please set this to true if your field only renders text.

This means it will never render a component in a table, because the value will always be text. When having lots of columns and rows it can get intensive for Vue to render these components.

We can use this field now in our resources, or on a custom page:

public function fields(): FieldCollection
{
return new FieldCollection(
Example::make(__('My label'), 'table_column_name'),
);
}

Front-end

Let's create an Example directory in components/fields.

Field in the form

The field is used in the forms. Properties like validation errors, debouncing, hints and more can be defined.

Example/Field.vue
<template>
<!-- The input, fieldProps contain label, validation messages etc. -->
<q-input
v-bind="fieldProps"
:rules="rules"
v-model="value"
debounce="250"
@input="onInput"
:type="type"
>
<!-- Mark label with a red star if required -->
<template v-slot:label>
<field-label :field="field"/>
</template>
<!-- Field hint -->
<template
v-slot:hint
v-if="field.hint"
>
{{ field.hint }}
</template>
<!-- Field tooltip -->
<template
v-if="field.tool_tip"
v-slot:after
>
<field-tooltip :field="field"/>
</template>
</q-input>
</template>

<script>
import Field from 'qore/mixins/resource/Field'

export default {
mixins: [Field],
methods: {
// setState will make sure the value is updated in the form
onInput() {
this.setState(this.field.name, this.value)
}
}
}
</script>

As you can see, we use the Field mixin. This mixin has all data from the form available (the other fields in the form, the values of these fields, error messages and more).

The Field mixin also exposes a setState method. This method will update the field value.

Field for the detail page

Example/Detail.vue
<template>
<div>
My detail for field: {{field.name}} with value: {{value}}
</div>
</template>

<script>
export default {
props: ['field', 'value']
}
</script>

Field for the index page

Example/Index.vue
<template>
<div>
My index for field: {{column.name}} with value: {{value}}
</div>
</template>

<script>
export default {
props: ['column', 'value']
}
</script>

Field for the table filter

Example/Filter.vue
<template>
<q-input
v-model="value"
dense
clearable
filled
debounce="250"
@input="onInput"
/>
</template>

<script>
import Filter from 'qore/mixins/resource/Filter'

export default {
mixins: [Filter],
methods: {
onInput() {
this.emitValue(this.value)
}
}
}
</script>

Similar to the Field.vue, the filter includes the Filter mixin. This mixin exposes the emitValue method to apply the filter.

Registering the components

Let's register our example components in boot/fields.js:

import ExampleField from 'components/fields/Example/Field'
import ExampleDetail from 'components/fields/Example/Detail'
import ExampleIndex from 'components/fields/Example/Index'
import ExampleFilter from 'components/fields/Example/Filter'

Vue.component('ExampleField', ExampleField)
Vue.component('ExampleDetail', ExampleDetail)
Vue.component('ExampleIndex', ExampleIndex)
Vue.component('ExampleFilter', ExampleFilter)