DisForm.vue
For developers
A deep dive into the code behind the Template-Manager, which comprises the mDIS interactive form designer.
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 inDisFilterForm
.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 theDisFilterForm.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 runnpm run build
.
To make form specialization easier to understand, we will start from this 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"
}
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
}
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:
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'"/>
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'"/>
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):
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>
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 theVuetify
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.
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'"/>
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('[]')
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>
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 tov-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"}]')
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):
Exercises
- Test the form reactivity: Update any value of any record. Are the calculated fields updated immediately? Are they displayed correctly?
- 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-slot
s 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>
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>
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.
Now read the official Slot documentation (opens new window).