# Form
The create and edit pages will allow creation of new resource item or modification of existing method, by using respectively create
and update
data provider methods. In general this pages will share same form although it is not required. With Vuetify Admin, development of form can be done with minimal code thanks to many available input components that have knowledge of current form context.
# Layouts
Both create and edit layouts share similar layout as show page with specific contextualized actions. There is nothing more to say about them as the VaForm
will do the real work.
# Create layout
VaCreateLayout
Page layout for resource creation.
MIXINS
PROPS
Props | Type | Description |
---|---|---|
title | string | Optional H1 title of the page shown on the left of top header |
SLOTS
Name | Description |
---|---|
actions | Additional custom action buttons placeholder. |
default | Page content placeholder. |
CLONE
Note that the create page support copy of values from other existing resource, i.e. cloning, as soon as a specific source
query string with a valid existing id is present. This is automatically done via VaCloneButton
present by default on VaDataTable
. This is why a item
prop is available on Create
vue component that allows you to inject it into VaForm
.
<template>
<va-create-layout>
<va-form :item="item">
<!-- VA inputs component -->
</va-form>
</va-create-layout>
</template>
<script>
export default {
props: ["item"],
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
# Edit layout
VaEditLayout
Page layout for resource edition. Contain specific related action as deleting, cloning, showing as well as translation action.
MIXINS
PROPS
Props | Type | Description |
---|---|---|
title | string | Optional H1 title of the page shown on the left of top header |
SLOTS
Name | Description |
---|---|
actions | Additional custom action buttons placeholder. |
default | Page content placeholder. |
USE ID
Compared to to create page, you gain a new id
prop that correspond to the resource to edit and patch on the API side. Don't forget to put it on form via the same prop in order to use update
data provider method under the hood.
<template>
<va-edit-layout>
<va-form :id="id" :item="item">
<!-- VA inputs component -->
</va-form>
</va-edit-layout>
</template>
<script>
export default {
props: ["id", "item"],
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
# Tabbed layout
As the same way for the show view, you have total freedom for page templating. Example with a tabbed style form :
Here a code sample :
<template>
<va-edit-layout>
<va-form :id="id" :item="item">
<v-row justify="center">
<v-col lg="8">
<base-material-tabs-card
:tabs="[
{ id: 'attributes', icon: 'mdi-eye' },
{ id: 'summary', icon: 'mdi-text' },
]"
>
<template v-slot:attributes>
<!-- 1st tab content -->
</template>
<template v-slot:summary>
<!-- 2st tab content -->
</template>
</base-material-tabs-card>
</v-col>
</v-row>
</va-form>
</va-edit-layout>
</template>
<script>
export default {
props: ["title", "id", "item"],
};
</script>
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
# Injector
VaForm
Form component which handle resource saving by calling create
or update
data provider methods.
It's the better place for made heavy usage of any VA inputs.
Use injection which allowing unique global v-model for all inputs.
MIXINS
PROPS
Props | Type | Description |
---|---|---|
v-model | object | Current form model being edited. Represent the final data that will be send through your API. |
id | string|number | Id of resource to be edit. If null, then create a new one. |
item | object | Explicit item resource object where all properties must be injected into form model. |
redirect | string | Default route resource action to redirect after saving. |
disableRedirect | boolean | Disable default redirect behavior |
SLOTS
Name | Description |
---|---|
default | All content form with all inner inputs. Model will be injected for each inputs. |
EVENTS
Name | Description |
---|---|
input | Send model update, called after each single input change. |
saved | Sent after success saving. |
Here a quick sample usage within the VaForm
inside a VaEditLayout
component :
<template>
<va-form :id="id" :item="item">
<v-row justify="center">
<v-col lg="6">
<base-material-card>
<template v-slot:heading>
<div class="display-2">
{{ title }}
</div>
</template>
<v-card-text>
<va-autocomplete-input
source="book"
reference="books"
model="book_id"
></va-autocomplete-input>
<va-radio-group-input source="status" row></va-radio-group-input>
<va-rating-input source="rating"></va-rating-input>
<va-text-input source="body" multiline></va-text-input>
<va-text-input source="author"></va-text-input>
<va-date-input source="publication_date"></va-date-input>
</v-card-text>
<va-save-button></va-save-button>
</base-material-card>
</v-col>
</v-row>
</va-form>
</template>
<script>
export default {
props: ["id", "title", "item"],
};
</script>
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
This form page will use special VA input components that are aware of current route context and are able to catch and edit the value of resource property indicated on the source
prop.
Note that the main internal form model will be auto generated from all inputs that will be present on this form. If you inject an existing item into VaForm
, the main form model will takes his actual values that will be reflected for each input.
ALL INPUT COMPONENTS
Go to separated inputs guide reference to get all supported components for edit data. You can still create your own input component if none suit your needs.
# Saving and redirect
Use the VaSaveButton
as default submit button. It will automatically synchronize with parent form in order to active the spinner while saving to the API.
<template>
<va-form :id="id" :item="item" redirect="show">
<!-- VA inputs component -->
<va-save-button></va-save-button>
</va-form>
</template>
<script>
export default {
props: ["id", "title", "item"],
};
</script>
2
3
4
5
6
7
8
9
10
11
12
By default a successful saving will redirect to resource list page unless you set explicit redirect
on VaForm
prop as above. Note as this prop have only effect for a submit button. Moreover, you can set redirect
on VaSaveButton
. It will disable the default submit behavior and the user must click or key press on it for saving. Particularly useful when you need multiple redirect actions as shown next :
<template>
<va-form :id="id" :item="item">
<!-- VA inputs component -->
<va-save-button></va-save-button>
<va-save-button
text
redirect="create"
color="secondary"
></va-save-button>
</va-form>
</template>
<script>
export default {
props: ["id", "title", "item"],
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
It will render 2 different buttons, the default one that will submit on enter and redirect to list, and an additional save and add button :
NO DEFAULT REDIRECT
Use disable-redirect
prop on VaForm
in order to prevent default submit redirect. No effect on save buttons with redirect.
# Form model
As you can see on above code sample, there is no need of any v-model in order to make it work. Indeed, all child inputs will receive the parent form state via provide/inject (opens new window) Vue feature, which reduces considerably code form boilerplate. All inputs will update the internal parent model accordingly on first input initialization and on every input change.
But what if we need access to internal form model for specific case, as show/hide some fields based on current model state ? For that you just have to expose the internal form model via v-model
.
Here is a full example with show/hide some fields based on active
property model :
<template>
<va-form :id="id" :item="item" v-model="model">
<va-text-input source="description" multiline></va-text-input>
<va-boolean-input source="active"></va-boolean-input>
<v-row v-if="model.active">
<v-col sm="6">
<va-text-input source="url"></va-text-input>
</v-col>
<v-col sm="6">
<va-text-input source="email"></va-text-input>
</v-col>
</v-row>
<va-save-button></va-save-button>
</va-form>
</template>
<script>
export default {
props: ["id", "title", "item"],
data() {
return {
model: {
active: true,
},
};
},
};
</script>
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
DEFAULT VALUE
Note that you're not forced to put all properties inside exposed model. If not present, they will still auto created by all present VA inputs component.
If you explicitly set a property, the related input will take this value as default in case of no item is injected into VaForm
. Ideal for pre filling a create item.
If you don't need a v-model
, simply set the value
prop to any compatible value. This value will be take as default on create form.
You can even use the v-model on VA input instead of full form :
<template>
<va-form :id="id" :item="item">
<va-text-input source="description" multiline></va-text-input>
<va-boolean-input source="active" v-model="active"></va-boolean-input>
<v-row v-if="active">
<v-col sm="6">
<va-text-input source="url"></va-text-input>
</v-col>
<v-col sm="6">
<va-text-input source="email"></va-text-input>
</v-col>
</v-row>
<va-save-button></va-save-button>
</va-form>
</template>
<script>
export default {
props: ["id", "title", "item"],
data() {
return {
active: true,
};
},
};
</script>
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
# Client-side validation
VaForm
use a vuetify v-form
under the hood. Check the official docs (opens new window) for further detail. Use the rules
property for each VA inputs for setting custom rules. For required, you can use the required
shorthand prop.
# Server-side validation
ERRORS HANDLING
See separated section before continue.
Server-side validation is supported as soon as your API provides all constraint violations inside response body, which usually wears a 422
status code. VaForm
will search for a errors
property on the error object returned by your data provider and will dispatch them to all input fields.
This errors
property is a key-value object where each property have the list of associated errors. The name of each property must correspond to the source
defined on each input in order to push errors on it via his errorMessages
prop.
Here an example of compatible object error :
{
"message": "The given data was invalid.",
"status": 422,
"errors": {
"book_id": ["The book id field is required."],
"status": ["The status field is required."],
"author": ["The author field is required."],
"publication_date": ["The publication date field is required."]
}
}
2
3
4
5
6
7
8
9
10
It will render as next :