DisForm.vue

Developer page

For developers

A deep dive into the code behind the Template-Manager, which comprises the mDIS interactive form designer.

single-tile

Purpose of DisForm

DisForm is a feature-rich Vue component that is used to filter, list and update the data records of a data model (table). Using the Template-Manager, mDIS Admins design new tables/models and new data input forms that are typically based on DisForm. The newly generated "artifacts" - a set of .vue files, .json files and others (PHP files) - can then be customized. In Legacy DIS, a similar process (of customizing data-models and input forms) was also known as specialization.

WARNING

Files src/components/DisForm.vue and its container src/components/DisSmartForm.vue should not be changed by any user.

The <template> section of DisForm typically contains two other Form components which should not be changed either:

  • DisFilterForm.vue: Implements the Filter Bar visible at the top of each form. DisFilterForm is used to render the filter components and filter-by-value form. This component updates the current URL query parameters corresponding to the selected filter component's value. It also offers a modal Filter-by-Values dialog-box that processes the new filter expressions entered by the user. The filter settings then "trickle through" the other components embedded in the form, and the filter is applied on the record-listing, at the bottom of the page.
    After receiving the new value of a filter expression, all affected components update themselves. This process is triggered by events emitted by changes in DisFilterForm.
  • DisDataTable.vue which lists and paginates the linked table records. The listing depends on the current filter settings, visible as URL parameters in the browser's address bar on the current page. Alternatively, the listing may also depend on the current filter-by-value settings obtained from the DisFilterForm.vue component (in case this dialog box was used).

The <script> section of DisForm contains a rich data array and a lot of props and methods. There are too many to discuss them here. Most of them are either Click-handlers for the many buttons inside the navigation bar and filter bar, or other types of Event Listeners.

Tutorial: customizing a .vue file

Form Specialization: Data Fields

Forms generated by mDIS admins are typically based on DisForm. The new forms can be customized, or specialized. The remainder of this document is a tutorial how to perform various customizations on a file SampleForm.vue. (You might use a different name for your form, and that's okay.)

About this Tutorial

  • This tutorial demonstrates how to customize the forms with a text editor, by editing the generated source code.
  • Therefore, the Templates-Manager GUI plays only a minor role in this tutorial, mainly during initial form generation.
  • If you follow along in your IDE, copy the sections in green font from the code blocks below. After pasting them into your SampleForm.vue file (or equivalent), remove the plus signs ( + ) from the beginning of each line!
  • If you work in development mode (npm run serve), after saving any .vue file, the changes should be immediately visible in the browser. In production mode, you need to run npm run build.

To make form specialization easier to understand, we will start from this example:

form specialization example

A simple form with four fields. Here are the model templates and the form templates, both in JSON format:

Model Template

Generate this model with the Template-Manager. Alternatively, save this code into a .json file, then upload it with the "Upload a model template (*.json)" feature of the Template-Manager. "Save & Generate" the model.

On line 2, 3, and 4 of the following code, you can change the "module", "name", and "table" entries to something you prefer. ("module" means "TableSet", "name" is the Model Name as it appears on the web page, and "table" is the name of the database table. Avoid blanks ``.):

{
    "module": "Sa",
    "name": "Sample",
    "table": "sa_sample",
    "importTable": null,
    "parentModel": "",
    "columns": {
        "id": {
            "name": "id",
            "importSource": "",
            "type": "integer",
            "size": 11,
            "required": false,
            "primaryKey": true,
            "autoInc": true,
            "label": "ID",
            "description": "",
            "validator": "",
            "validatorMessage": "",
            "unit": "",
            "selectListName": "",
            "calculate": "",
            "defaultValue": ""
        },
        "title": {
            "name": "title",
            "importSource": "",
            "type": "string",
            "size": 50,
            "required": true,
            "primaryKey": false,
            "autoInc": false,
            "label": "Title",
            "description": "The title of this record",
            "validator": "",
            "validatorMessage": "",
            "unit": "",
            "selectListName": "",
            "calculate": "",
            "defaultValue": ""
        },
        "slug": {
            "name": "slug",
            "importSource": "",
            "type": "string",
            "size": 100,
            "required": false,
            "primaryKey": false,
            "autoInc": false,
            "label": "Slug",
            "description": "A unique kebab-case title",
            "validator": "",
            "validatorMessage": "",
            "unit": "",
            "selectListName": "",
            "calculate": "",
            "defaultValue": ""
        },
        "depth": {
            "name": "depth",
            "importSource": "",
            "type": "double",
            "size": null,
            "required": true,
            "primaryKey": false,
            "autoInc": false,
            "label": "Depth",
            "description": "Depth in meters",
            "validator": "",
            "validatorMessage": "",
            "unit": "",
            "selectListName": "",
            "calculate": "",
            "defaultValue": ""
        },
        "depth_mm": {
            "name": "depth_mm",
            "importSource": "",
            "type": "double",
            "size": null,
            "required": true,
            "primaryKey": false,
            "autoInc": false,
            "label": "Depth Mm",
            "description": "Depth in millimeteres",
            "validator": "",
            "validatorMessage": "",
            "unit": "",
            "selectListName": "",
            "calculate": "",
            "defaultValue": ""
        }
    },
    "indices": {
        "pk_id": {
            "name": "pk_id",
            "type": "PRIMARY",
            "columns": [
                "id"
            ]
        },
        "unique_slug": {
            "name": "unique_slug",
            "type": "UNIQUE",
            "columns": [
                "slug"
            ]
        }
    },
    "foreignkeys": [],
    "createdAt": 1556631283,
    "modifiedAt": 1556631295,
    "generatedAt": 1556631298,
    "fullName": "SaSample"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

Form Template

Generate this form with the Forms-Manager, or upload it with the "Upload a form template (*.json)" feature of the Template-manager. "Save & Generate" the form. Note the file names that are being generated.

{
    "name": "sample",
    "dataModel": "SaSample",
    "fields": [
        {
            "name": "title",
            "label": "Title",
            "description": "The title of this record",
            "validators": [
                {
                    "type": "required"
                },
                {
                    "type": "string"
                }
            ],
            "formInput": {
                "type": "text",
                "disabled": false,
                "calculate": "",
                "jsCalculate": ""
            },
            "group": "-group1",
            "order": 0
        },
        {
            "name": "slug",
            "label": "Slug",
            "description": "A unique kebab-case title",
            "validators": [
                {
                    "type": "string"
                }
            ],
            "formInput": {
                "type": "text",
                "disabled": false,
                "calculate": "",
                "jsCalculate": ""
            },
            "group": "-group1",
            "order": 1
        },
        {
            "name": "depth",
            "label": "Depth",
            "description": "Depth in meters",
            "validators": [
                {
                    "type": "required"
                },
                {
                    "type": "number"
                }
            ],
            "formInput": {
                "type": "text",
                "disabled": false,
                "calculate": "",
                "jsCalculate": ""
            },
            "group": "Meta Data",
            "order": 0
        },
        {
            "name": "depth_mm",
            "label": "Depth Mm",
            "description": "Depth in millimeteres",
            "validators": [
                {
                    "type": "required"
                },
                {
                    "type": "number",
                    "min": null,
                    "max": null
                }
            ],
            "formInput": {
                "type": "text",
                "disabled": false,
                "calculate": "[depth] * 100",
                "jsCalculate": "this.formModel['depth'] * 100"
            },
            "group": "Meta Data",
            "order": 1
        }
    ],
    "filterDataModels": [],
    "requiredFilters": [],
    "subForms": [],
    "supForms": [],
    "createdAt": 1556631418,
    "modifiedAt": 1556631472,
    "generatedAt": 1556631490
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

With this example we will demonstrate a typical form specialization case.

The first step is to remove the .generated extension from the generated form file. In directory src/forms, rename the file SampleForm.vue.generated to SampleForm.vue.

In the TemplatesManager/FormsManager GUI, a warning appears:

renamed-warning

Be careful during later runs of the form-generator for that model, you might overwrite your own changes. Put the files you customized under version control (git). For this tutorial, this is not really necessary.

Toggle editable/uneditable

In SampleForm.vue find the textfield you want to edit, and simply change the value of the disabled property from false to true:

<DisTextInput
    :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['title'] !== formModel['title']}"
-    :disabled="false"
+    :disabled="true"
    :validators="validators['title']"
    name="title"
    label="Title"
    :serverValidationErrors="serverValidationErrors"
    hint="The title of this record"
    v-model="formModel['title']"
    :readonly="formScenario === 'view'"/>
1
2
3
4
5
6
7
8
9
10
11

This edit can also be done via Template manager. But for demonstration purposes we change the file src/forms/SampleForm.vue.

Hide/unhide

This edit is similar to the previous edit above. But this time add attribute v-show (opens new window) to control the field visibility:

<DisTextInput
    :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['title'] !== formModel['title']}"
    :disabled="false"
+    v-show="false"
    :validators="validators['title']"
    name="title"
    label="Title"
    :serverValidationErrors="serverValidationErrors"
    hint="The title of this record"
    v-model="formModel['title']"
    :readonly="formScenario === 'view'"/>
1
2
3
4
5
6
7
8
9
10
11

If the line with v-show is not there, you must add it.

Now the form should look like this (details can differ):

invisible

Change field widths

The fields are arranged using a Vuetify layout scheme called "Grid System" (opens new window). You are free to modify the grid, and thus to re-arrange the input fields, as you wish. As an example, we will change the layout from a 2x2 grid to a 4x1 grid, thus render every field on its own full row. We accomplish this by removing the four "md3 sm6" snippets from the SampleForm.vue file.

<v-layout wrap mb-3>
    <v-flex xs12 pl-2 pt-2>
        -group1
    </v-flex>
-    <v-flex lg2 md3 sm6 xs12 pr-2 pl-2>
+    <v-flex lg2         xs12 pr-2 pl-2>
        <DisTextInput name="title"/>
    </v-flex>
-    <v-flex lg2 md3 sm6 xs12 pr-2 pl-2>
+    <v-flex lg2         xs12 pr-2 pl-2>
        <DisTextInput name="slug"/>
    </v-flex>
</v-layout>
<v-layout wrap mb-3>
    <v-flex xs12 pl-2 pt-2>
        Meta Data
    </v-flex>
-    <v-flex lg2 md3 sm6 xs12 pr-2 pl-2>
+    <v-flex lg2         xs12 pr-2 pl-2>
        <DisTextInput name="depth"/>
    </v-flex>
-    <v-flex lg2 md3 sm6 xs12 pr-2 pl-2>
+    <v-flex lg2         xs12 pr-2 pl-2>
        <DisTextInput name="depth_mm"/>
    </v-flex>
</v-layout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

These changes effectively remove the table rendering rules for medium (md) screens and small (sm) screens, treating all screens as extra small. This forces a full-width rendering on most screens, regardless of size. (The terms md3, sm6 etc are CSS classes from the Vuetify component library which itself is inspired by Bootstrap.)

Result:

Note the larger widths of the input fields after changing the 2x2 grid to a 4x1 grid.

example for changing form layout

Change field order

Changing the order of the fields is also possible. but it's not shown here. Simply switch positions of any DisTextInput elements inside the Sample.vue file.

This feature is available via Template manager, too. Drag-and-drop the field positions.

Set label/hint

This change can be demonstrated with another couple of very simple one-liners:

<DisTextInput
    :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['depth'] !== formModel['depth']}"
    :disabled="false"
    :validators="validators['depth']"
    name="depth"
-    label="Depth"
+    label="Driller Depth"
    :serverValidationErrors="serverValidationErrors"
-    hint="Depth in meters"
+    hint="Driller Depth in meters"
    v-model.number="formModel['depth']"
    :readonly="formScenario === 'view'"/>
1
2
3
4
5
6
7
8
9
10
11
12

(Result not shown)

Available via Template manager, too.

Calculated fields

Let's try an advanced example: Add a new field error_estimate that is calculated on the fly.

In principle, available via Templates/Forms Manager GUI, too. Here we accomplish this in code, with more fine-grained control.

In the <script> element of the Sample.vue file, after the this.simpleFields = ... line insert the following Javascript code.

This JS snippet adds a textfield definition error_estimate that does not exist in the model. Nevertheless it will be displayed on the form:

this.simpleFields = JSON.parse('[{"name":"title","label":"Title","description":"The title of this record","group":"-group1","order":0,"inputType":"text"},{"name":"slug","label":"Slug","description":"A unique kebab-case title","group":"-group1","order":1,"inputType":"text"},{"name":"depth","label":"Depth","description":"Depth in meters","group":"Meta Data","order":0,"inputType":"text"},{"name":"depth_mm","label":"Depth Mm","description":"Depth in millimeteres","group":"Meta Data","order":1,"inputType":"text"}]')
+    this.simpleFields.push({
+      name: 'error_estimate',
+      label: 'Error Estimate',
+      description: 'Displays an error estimate of the Driller Depth',
+      group: 'Meta Data',
+      order: 2,
+      inputType: 'text'
+    })
    this.requiredFilters = JSON.parse('[]')
    this.subForms = JSON.parse('[]')
1
2
3
4
5
6
7
8
9
10
11

Previously, in Section "Hide/unhide", you have changed a <DisTextInput> element by setting v-show= "false". In the <template> element of the Sample.vue file, find that <DisTextInput> element. Immediately before the opening <DisTextInput>, add the following HTML/Vue code (without +s). The green snippet defines an input field for the new field error_estimate:

    <v-flex xs12 pr-2 pl-2>
        <DisTextInput
            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['depth_mm'] !== formModel['depth_mm']}"
            :disabled="true"
            :validators="validators['depth_mm']"
            name="depth_mm"
            label="Depth Mm"
            :serverValidationErrors="serverValidationErrors"
            hint="Depth in millimeteres"
            v-model.number="formModel['depth_mm']"
            :readonly="formScenario === 'view'"/>
    </v-flex>
+    <v-flex xs12 pr-2 pl-2>
+        <DisTextInput
+            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['error_estimate'] !== formModel['error_estimate']}"
+            :disabled="true"
+            :validators="validators['error_estimate']"
+            name="error_estimate"
+            label="Error Estimate"
+            :serverValidationErrors="serverValidationErrors"
+            hint="Displays an error estimate of the Driller Depth"
+            v-model.number="formModel['error_estimate']"
+            :readonly="formScenario === 'view'"/>
+    </v-flex>
</v-layout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Developers: It is important to make the field reactive. We do this by binding formModel['error_estimate'] object to v-model, see third green line from below.

At this time, we have a new text field error_estimate, but the field is empty. This is because the form does not do any estimations yet.

In the <script> element of the Sample.vue file, add this Javascript code. This code defines a custom anonymous function (){ } with a primitive "error estimation algorithm".

Add the this.calculatedFields['error_estimate'] object property:

this.calculatedFields = {}
    this.calculatedFields['depth_mm'] = function () {
      return this.formModel['depth'] * 100
    }
+    this.calculatedFields['error_estimate'] = function () {
+      if (this.formModel['depth'] > 1000) {
+        return 'About 1 m'
+      }
+      if (this.formModel['depth'] > 500) {
+        return 'About 0.5 m'
+      }
+      if (this.formModel['depth'] > 250) {
+        return 'About 0.10 m'
+      }
+      if (this.formModel['depth'] > 100) {
+        return 'About 0.01 m'
+      }
+      return 'Not Enough Data!'
+    }

    this.simpleFields = JSON.parse('[{"name":"title","label":"Title","description":"The title of this record","group":"-group1","order":0,"inputType":"text"},{"name":"slug","label":"Slug","description":"A unique kebab-case title","group":"-group1","order":1,"inputType":"text"},{"name":"depth","label":"Depth","description":"Depth in meters","group":"Meta Data","order":0,"inputType":"text"},{"name":"depth_mm","label":"Depth Mm","description":"Depth in millimeteres","group":"Meta Data","order":1,"inputType":"text"}]')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Result (Note the new "Error Estimate" text field):

advanced calculation example

Exercises

  1. Test the form reactivity: Update any value of any record. Are the calculated fields updated immediately? Are they displayed correctly?
  2. Add a similar calculation rule for the "Depth mm" field. It should take the value of Depth (m) and multiply it with 100.

Vue Slots

At a glance

Slots could be used to inject static content, e.g. text blocks such as "How-To" descriptions, into forms with complicated data entry requirements, or to add further instrutions for mDIS operators.

This tutorial here is only very basic, and does only scratch the surface of what is possible with Vue Slots.

In mDIS, v-slots are being used at least 25 .vue-files, not only in DisForm.vue. <slot> Elements are used in at least 7 .vue-files.

Vue Slot Code in DisForm.vue

The <template> elements of the DisForm and DisSmartForm components each contain two named <slot> elements: slot form-fields and slot extra-form-actions. These are Vue scoped named slots (opens new window) that could be used for form specialization. (Scoped slots have access to data only available in the child component. Named slots are different from the default slot of which there may exist only one per <template> block. Named slots thus are more flexible than default slots.)

There are many more slots defined in the mDIS .vue files but let's discuss the form-fields and extra-form-actions slots.

Slots and Slot-Props vs. Props

<slot></slot> Elements (Vue Slots (opens new window)) and v-slot attributes ("Slot-props") can be used to pass Template Code and HTML fragments between Vue components. Slots can pass HTML better than Vue Props (opens new window), which are more suitable for JS code snippets.

Now you should take a look at source code of file src/components/DisForm.vue, where the slots are defined. (The line numbers are lines ~27 and ~132. Do not change the file).

Slot "form-fields"

As the name states, the content of this slot will be rendered in the position where the form fields reside. This slot provides access to the following variables in DisForm.vue:

formScenario

The current form scenario. create, edit or view

selectedItem

The current selected item (the selected item in the list)

formModel

An object that holds the current record that is loaded on the form

serverValidationErrors

The validation errors that are returned form the server will be assigned to this variable.

Slot "extra-form-actions"

The content of this slot will be rendered at the bottom of the form. By default, the child / parent forms are rendered in this slot. This slot provides access to the following:

selectedItem.

The current selected item (the selected item in the list)

onSubFormClick

event handler for the child forms (see implementation in DisForm.vue)

onSupFormClick

event handler for the parent forms (see implementation in DisForm.vue)

Customizing .vue File (cont'd)

Continue customizing SampleForm.vue. See next long code snippet below.

Insert extra component

See this example. On lines ~ 84-100 of SampleForm.vue, we add new code via the extra-form-actions slot, to embed a small clickable picture on the form.

You could add/pass any component (icon, static image, link, button, ...etc) in the two available slots.

We insert an additional Vue-template fragment <v-flex><h3>Extra Elements</h3><v-layout>...</v-layout></v-flex> into the form's template v-slot:... element (on line 6).

If <template v-slot:form-fields=...> did not contain a v-slot attribute ("slot-prop"), any unkown components provided between its opening and closing tag would be discarded by Webpack.

Instead, because it is part of a v-slot, this will be converted to HTML, and then be displayed on the form. But the injected HTML is not part of the model, hence it is not stored inside the database.

<!-- SampleForm.vue -->
<template>
    <v-container fluid>
        <v-flex align-start>
            <h2>Sample</h2>
            <dis-form formName="sample" dataModel="SaSample" :fields="simpleFields" :requiredFilters="requiredFilters" :filterDataModels="filterDataModels" :calculatedFields="calculatedFields">
                <template v-slot:form-fields="{fields, hasNumberValidator, getInputComponent, formScenario, selectedItem, formModel, serverValidationErrors}">
                    <v-layout wrap lg-2>
                        <v-flex md12 lg6 pr-2 pl-2>
                            <v-layout wrap mb-3>
                                <v-flex xs12 pl-2 pt-2 class="title">
                                    Basic Info
                                </v-flex>
                                <v-flex xs12 pr-2 pl-2>
                                    <DisTextInput
                                            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['title'] !== formModel['title']}"
                                            :disabled="false"
                                            :validators="validators['title']"
                                            name="title"
                                            label="Title"
                                            :serverValidationErrors="serverValidationErrors"
                                            hint="The title of this record"
                                            v-model="formModel['title']"
                                            :readonly="formScenario === 'view'"/>
                                </v-flex>
                                <v-flex xs12 pr-2 pl-2>
                                    <DisTextInput
                                            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['slug'] !== formModel['slug']}"
                                            :disabled="false"
                                            :validators="validators['slug']"
                                            name="slug"
                                            label="Slug"
                                            :serverValidationErrors="serverValidationErrors"
                                            hint="A unique kebab-case title"
                                            v-model="formModel['slug']"
                                            :readonly="formScenario === 'view'"/>
                                </v-flex>
                            </v-layout>
                        </v-flex>
                        <v-flex md12 lg6 pr-2 pl-2>
                            <v-layout wrap mb-3>
                                <v-flex xs12 pl-2 pt-2 class="title">
                                    Meta Data
                                </v-flex>
                                <v-flex xs12 pr-2 pl-2>
                                    <DisTextInput
                                            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['depth'] !== formModel['depth']}"
                                            :disabled="false"
                                            :validators="validators['depth']"
                                            name="depth"
                                            label="Depth"
                                            :serverValidationErrors="serverValidationErrors"
                                            hint="Depth in meters"
                                            v-model.number="formModel['depth']"
                                            :readonly="formScenario === 'view'"/>
                                </v-flex>
                                <v-flex xs12 pr-2 pl-2>
                                    <DisTextInput
                                            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['depth_mm'] !== formModel['depth_mm']}"
                                            :disabled="true"
                                            :validators="validators['depth_mm']"
                                            name="depth_mm"
                                            label="Depth Mm"
                                            :serverValidationErrors="serverValidationErrors"
                                            hint="Depth in millimeteres"
                                            v-model.number="formModel['depth_mm']"
                                            :readonly="formScenario === 'view'"/>
                                </v-flex>
                                <v-flex xs12 pr-2 pl-2>
                                    <DisTextInput
                                            :class="{'c-dis-form__input': true, 'c-dis-form__input--modified': formScenario === 'edit' && selectedItem['depth_mm'] !== formModel['depth_mm']}"
                                            :disabled="true"
                                            :validators="validators['estimation']"
                                            name="estimation"
                                            label="Estimation"
                                            :serverValidationErrors="serverValidationErrors"
                                            hint="Gives an opinion about the depth"
                                            v-model="formModel['estimation']"
                                            :readonly="formScenario === 'view'"/>
                                </v-flex>
                            </v-layout>
                        </v-flex>
                        <v-flex xs12 pr-2 pl-2>
                            <h3>Extra Elements</h3>
                            <v-layout>
                                <v-flex xs12 sm4 md3 lg2>
                                    <v-card color="pink" shrink>
                                    <!-- src="img/other/odai-gravatar.jpeg">-->
                                        <v-img aspect-ratio="1" as src="https://s.gravatar.com/avatar/44c354b4bf3f25ec87a63c21ba36f590?s=400">
                                        </v-img>
                                        <v-card-title primary-title>
                                            Hey how are you today?
                                        </v-card-title>
                                        <v-card-actions>
                                            <v-btn flat @click="onGoToCoresClick">Go to Cores form</v-btn>
                                        </v-card-actions>
                                    </v-card>
                                </v-flex>
                            </v-layout>
                        </v-flex>
                    </v-layout>
                </template>
            </dis-form>
        </v-flex>
    </v-container>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

We can even add JavaScript code that refers to the above-mentioned HTML/Vue code. For example, we can register a click-handler on the dynamically-injected HTML snippet. Add this change to the <script> element. (The added lines are shown in green font):

    this.simpleFields.push({
      name: 'estimation',
      label: 'Estimation',
      description: 'Gives an opinion about the depth',
      group: 'Meta Data',
      order: 2,
      inputType: 'text'
    })
    this.requiredFilters = JSON.parse('[]')
    this.subForms = JSON.parse('[]')
    this.supForms = JSON.parse('[]')
    this.filterDataModels = JSON.parse('{}')
-  }
+  },
+  methods: {
+    onGoToCoresClick () {
+      this.$router.push('/forms/cores-form')
+    }
+  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

What just happened?

  • In the first part of the tutorial, the fields layout was changed (From 4 to 5 text fields. Field ErrorEstimate is new.)
  • An Extra element was added using Vuetify cards (opens new window) (the blue/pink picture)
  • A button with a customized click handler was added to the card (A click on "GO TO CORES" text below will open the Cores Form)

Result

The "GO TO CORES" string in the picture is actually a clickable link.

example 3

Now read the official Slot documentation (opens new window).