@ferchoposting/formie
v1.0.516
Published
Create forms with Vue 3 easily, extensively and with fun!
Downloads
27
Maintainers
Readme
Requirements
Formie was designed to be easily integrated with Laravel v8 + Jetstream + Inertia (vue3)
- Tailwind.css
- Inertia.js
Installation
Install with npm
npm install @ferchoposting/formie
Import library and input
import { Formie, inputs } from "@ferchoposting/formie";
Add components to tailwind purge components otherwise the css of components won't load.
tailwind.config.js
{
...
purge: [
...,
'./node_modules/@ferchoposting/formie/**/*.vue',
],
}
Introduction
Create login form
<template>
<div class="max-w-md mt-12 mx-auto">
<formie :form="form" />
</div>
</template>
<script>
import { Formie } from "@ferchoposting/formie";
export default {
components: {
Formie,
},
setup() {
const form = [
// Username field
{
name: "username",
label: "Username or email",
type: "text",
},
// Password field
{
name: "password",
label: "Your secret password",
type: "password",
},
];
return { form };
},
};
</script>
The result will be a simple login form:
Yeah but... How do I get the info?
Copy and paste the following code:
<template>
<div class="max-w-md mt-12 mx-auto">
<formie :form="form" />
</div>
</template>
<script>
import { Formie, inputs } from "@ferchoposting/formie";
export default {
components: {
Formie,
},
setup() {
const form = [
// Username field
{
name: "username",
label: "Username or email",
type: "text",
},
// Password field
{
name: "password",
label: "Your secret password",
type: "password",
},
// Buttons
{
type: inputs.Buttons,
buttons: [
{
label: "Login",
clicked(context) {
alert(`User: ${context.values.username}!`);
},
},
],
},
];
return { form };
},
};
</script>
The clicked function will be executed when button is clicked.
Context object
const context = {
// Object containing the user input on fields.
values: Object,
// The <model> with existing data supplied to form.
model: Object,
// The form object returned in setup function
form: Object,
// Form errors returned by inertia
errors: Object,
// Shortcut to model.id if exists else null.
id: [Number, null],
}
Available inputs
inputs.Buttons // Props: buttons
inputs.Default // Props: type
inputs.Checkbox // Props: default
inputs.Radio // Props: options
inputs.Select // Props: options
inputs.Textarea
inputs.Upload
Create custom input
You can return any vue component to the type
property on form fields object.
import CustomImageUploader from './CustomImageUploader.vue';
const form = [
{
label: "Fancy image uploader",
type: CustomImageUploader,
}
]
CustomImageUploader.vue
Props:
field
: Will be the object from the form (including label, type, etc)value
: Will be themodelValue
for fields, contains the model for the field.
Emits:
update
: Updates the value for the fieldfield
.
<script>
export default {
props: ["field", "value"],
emits: ["update"],
}
</script>
Copy paste example
ProductController.php
class ProductController extends Controller
{
public function create()
{
return inertia('Backend/Products/CreateEdit');
}
public function edit($id)
{
$model = Product::findOrFail($id);
return inertia('Backend/Products/CreateEdit', compact('model'));
}
}
CreateEdit.vue
<template>
<formie
:form="form"
:model="model"
:errors="$page.props.errors"
:debug="true"
/>
</template>
<script>
import { Formie } from "@ferchoposting/formie";
import form from './form.js';
export default {
props: ['model'],
components: {
Formie,
},
setup (props) {
return { form(props) };
}
}
</script>
form.js
import { Inertia } from '@inertiajs/inertia';
import { inputs } from "@ferchoposting/formie";
const onDelete = ({ id }) => {
if (id && confirm("Estas seguro?")) {
const url = route('products.destroy', id);
Inertia.delete(url);
}
};
const onSubmit = ({ id, values }) => {
const options = {
preserveScroll: true,
onSuccess: () => values.images_upload = null,
};
if (id) {
const url = route('products.update', id);
const data = {_method: 'PUT', ...values};
Inertia.post(url, data, options);
} else {
const url = route('products.store');
Inertia.post(url, values, options);
}
}
export default (props) => [
{
name: "name",
label: "Nombre del Producto",
type: "text"
},
{
name: "price",
label: "Precio",
type: "number"
},
{
name: "description",
label: "Descripción",
type: inputs.Textarea
},
{
name: "images_upload",
label: "Imágenes",
type: inputs.Upload,
multiple: true,
},
{
name: "category_id",
label: "Categoría",
type: inputs.Select,
attrs: {
class: "flex-col"
},
options: props.categories,
},
{
type: inputs.Buttons,
buttons: [
// Delete async button
function ({ id }) {
if (id) {
return {
label: "Eliminar",
class: "bg-red-700 text-white",
clicked: onDelete,
};
}
},
// Save button
{
label: "Guardar",
type: "submit",
clicked: onSubmit,
}
]
}
];