awes-io/form-builder
Awes-io/form-builder is a Laravel package for defining and rendering dynamic forms with a fluent PHP API. It supports validation, field types, actions, and Vue-powered rendering, making it easy to build admin forms and integrate them into AWES.io applications.
Confirm what you're actually installing before you start: awes-io/form-builder is part of the Awes.io front-end stack and is normally consumed as a Vue component (published under the @awes-io npm scope), not as a PHP service provider. Check the repo's package.json first — if there's no composer.json, treat this as a JS dependency that lives alongside your Laravel app, not a Laravel package you composer require.
Minimal path:
npm i @awes-io/form-builder or the git URL in the README), and make sure your Laravel app already has a Vue build (Laravel Mix or Vite with the Vue plugin). The Awes.io components assume a Vue 2-era stack and often expect awes-io/indigo-layout for base styling — install that too if the demo breaks visually.resources/js/app.js (Vue.component('form-builder', require('@awes-io/form-builder'))) or import it locally in the page component that needs it.src/ directory — the props API (value/v-model, field schema, slots) and the built-in field list are what you'll spend your time with. Ignore the build tooling until something breaks.<form-builder v-model="form"> with a small schema of text, textarea, and select fields, wire the submit/change event to a axios.post('/settings', this.form) against a standard Laravel controller + FormRequest. That exercises binding, defaults, and server round-trip in one pass.Schema-driven vs slot-driven fields. The component is built around a data object plus a field definition. For plain inputs, define fields declaratively (type, name, label, default). For anything non-trivial — a repeating "multi-block" section, a dependent field, a custom widget — use the package's named slots / custom field registration rather than fighting the built-in types. Keep custom fields in their own resources/js/components/fields/ directory and register them once.
Two-way binding with nested data. The main value is v-model against a plain object, so keep your form state as a single flat-ish object ({ name, email, address: { city } }) and let dot-notation field names map into it. This makes the whole form serializable in one JSON.stringify(this.form) on submit and keeps reset/dirty checks trivial (JSON.parse(JSON.stringify(initial))).
Custom multi-block fields. For repeatable groups, bind an array on the data object and use a custom field component that renders each entry plus add/remove buttons. Emit through the package's change mechanism so the parent form stays in sync — don't mutate the array from a sibling component or the form's dirty state will drift.
AJAX select. Use the package's async/AJAX select type with a load callback that hits a Laravel endpoint (/api/users?q=). Debounce input (~300ms), and return { value, label } pairs. Return a small per_page slice and let the component paginate/search rather than loading the whole table.
Backend integration. On submit, emit the data object and post it with Axios. Validate with a FormRequest and return 422 with Laravel's standard { errors: { field: [...] } }. Map those errors back onto the form by field name — this is the one place where dot-notation field names must match your validation rules exactly (address.city).
Workflow tip: keep the field schema in a separate JS module or serve it from the backend (GET /forms/profile) so the same schema drives both rendering and (optionally) validation hints. It makes adding a field a one-file change.
Vue.set/this.$set, or predefine the shape of the object before passing it in.user.name) can collide with literal dot-containing keys; be consistent and validate server-side with matching rule paths.AbortController/Axios cancel token) or tag responses with the query string and discard stale ones.array validation rule and your pivot/JSON column expectations must line up. Empty multi-selects often arrive as [] or null depending on config — normalize before saving.window/document; guard with <client-only> or process.client checks if you server-render.package.json and commit the lockfile. Upgrades are infrequent and may not follow semver strictly.input/change handler to see whether the emit fires or the binding is broken. Check the browser console for missing custom-field registrations.node_modules; the package is unlikely to be actively maintained, so your patches will be lost on reinstall.FormRequest — ownership and existence checks in particular.How can I help you explore Laravel packages today?