{"id":26085273,"url":"https://github.com/codezero-be/laravel-form-field-prefixer","last_synced_at":"2026-04-18T18:31:22.171Z","repository":{"id":56956035,"uuid":"253816533","full_name":"codezero-be/laravel-form-field-prefixer","owner":"codezero-be","description":"Reuse form partials and automatically add optional prefixes and array keys to your form fields.","archived":false,"fork":false,"pushed_at":"2023-03-01T12:15:47.000Z","size":54,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-12-08T12:33:04.601Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codezero-be.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"ko_fi":"ivanvermeyen","custom":"https://paypal.me/ivanvermeyen"}},"created_at":"2020-04-07T14:23:08.000Z","updated_at":"2023-10-28T13:37:42.000Z","dependencies_parsed_at":"2022-08-21T08:50:39.170Z","dependency_job_id":null,"html_url":"https://github.com/codezero-be/laravel-form-field-prefixer","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/codezero-be/laravel-form-field-prefixer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-form-field-prefixer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-form-field-prefixer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-form-field-prefixer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-form-field-prefixer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codezero-be","download_url":"https://codeload.github.com/codezero-be/laravel-form-field-prefixer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codezero-be%2Flaravel-form-field-prefixer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31979806,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T17:30:12.329Z","status":"ssl_error","status_checked_at":"2026-04-18T17:29:59.069Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-09T05:58:10.121Z","updated_at":"2026-04-18T18:31:22.125Z","avatar_url":"https://github.com/codezero-be.png","language":"PHP","funding_links":["https://ko-fi.com/ivanvermeyen","https://paypal.me/ivanvermeyen","https://ko-fi.com/R6R3UQ8V"],"categories":[],"sub_categories":[],"readme":"# Laravel Form Field Prefixer\n\n[![GitHub release](https://img.shields.io/github/release/codezero-be/laravel-form-field-prefixer.svg?style=flat-square)](CHANGELOG.md)\n[![Laravel](https://img.shields.io/badge/laravel-10-red?style=flat-square\u0026logo=laravel\u0026logoColor=white)](https://laravel.com)\n[![License](https://img.shields.io/packagist/l/codezero/laravel-form-field-prefixer.svg?style=flat-square)](LICENSE.md)\n[![Build Status](https://img.shields.io/scrutinizer/build/g/codezero-be/laravel-form-field-prefixer/master?style=flat-square)](https://scrutinizer-ci.com/g/codezero-be/laravel-form-field-prefixer/build-status/master)\n[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/codezero-be/laravel-form-field-prefixer/master?style=flat-square)](https://scrutinizer-ci.com/g/codezero-be/laravel-form-field-prefixer/?branch=master)\n[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/quality/g/codezero-be/laravel-form-field-prefixer/master?style=flat-square)](https://scrutinizer-ci.com/g/codezero-be/laravel-form-field-prefixer/?branch=master)\n[![Total Downloads](https://img.shields.io/packagist/dt/codezero/laravel-form-field-prefixer.svg?style=flat-square)](https://packagist.org/packages/codezero/laravel-form-field-prefixer)\n\n[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R3UQ8V)\n\n#### Reuse form partials with optional prefixes and array keys.\n\nWhen you have large forms and you want to split them up into reusable partials, you might end up doing some nasty logic inside the partials. To streamline this, I tucked away the logic behind the `FormFieldPrefixer` class.\n\n## ✅ Requirements\n\n- PHP \u003e= 7.1\n- Laravel \u003e= 5.6\n\n## 📦 Install\n\n```bash\ncomposer require codezero/laravel-form-field-prefixer\n```\n\n\u003e Laravel will automatically register the `FormFieldPrefixer` facade.\n\n## 🛠 Usage\n\n### Basic Usage - Simple Forms\n\nPass an instance of the `FormFieldPrefixer` to your form partial.\n\nOptionally you may provide an optional prefix to the `make` method:\n\n```blade\n@include('forms.address', ['prefixer' =\u003e FormFieldPrefixer::make('client')])\n```\n\nIf you don't provide a prefix, `client_` will be stripped of the example output below.\n\nInside the partial you can now use `$prefixer` to generate field names dynamically:\n\n#### Labels\n\nGenerate a `for` attribute:\n\n```blade\n\u003clabel {{ $prefixer-\u003efor('address') }}\u003eAddress:\u003c/label\u003e\n```\n\nThis will compile to:\n\n```blade\n\u003clabel for=\"client_address\"\u003eAddress:\u003c/label\u003e\n```\n\n#### Input Fields\n\nGenerate a `name`, `id` and `value` attribute:\n\nYou may pass an optional default value that will be filled in when the form loads.\n\nIf you submit the form and get redirected back with the input (like when you have validation errors), then the new values will override the default ones and will be filled in behind the scenes, using `Session::getOldInput($field)`.\n\n```blade\n\u003cinput\n    {{ $prefixer-\u003ename('address') }}\n    {{ $prefixer-\u003eid('address') }}\n    {{ $prefixer-\u003evalue('address', 'default value') }}\n\u003e\n```\n\nThis will compile to:\n\n```blade\n\u003cinput name=\"client_address\" id=\"client_address\" value=\"default value\"\u003e\n```\n\n#### Select Fields\n\nGenerate a `name` and `id` attribute for the select and a `selected` attribute for the selected option:\n\nThe `selected` method requires the option's value and accepts an optional default value to determine if the option is the selected one. In the example below `Mr.` is set as the default value.\n\nLike with the input field, old input has precedence over the default value.\n\n```blade\n\u003cselect {{ $prefixer-\u003ename('title') }} {{ $prefixer-\u003eid('title') }}\u003e\n    @foreach(['Mr.', 'Mrs.'] as $option)\n        \u003coption value=\"{{ $option }}\" {{ $prefixer-\u003eselected('title', $option, 'Mr.') }}\u003e\n            {{ $option }}\n        \u003c/option\u003e\n    @endforeach\n\u003c/select\u003e\n```\n\nThis will compile to:\n\n```blade\n\u003cselect name=\"client_title\" id=\"client_title\"\u003e\n    \u003coption value=\"mr\" selected=\"selected\"\u003eMr.\u003c/option\u003e\n    \u003coption value=\"mrs\"\u003eMrs.\u003c/option\u003e\n\u003c/select\u003e\n```\n\n#### Validation Errors\n\nGenerate a validation key you can pass to `@error`:\n\n```blade\n@error($prefixer-\u003evalidationKey('address'))\n    {{ $message }}\n@enderror\n```\n\nThis will compile to:\n\n```blade\n@error('client_address')\n    {{ $message }}\n@enderror\n```\n\n### Flat Array Forms\n\nIf you require, for example, multiple addresses, you can specify an array key for each partial:\n\n```blade\n@foreach(['billing', 'shipping'] as $type)\n    @include('forms.address', ['prefixer' =\u003e FormFieldPrefixer::make('client')-\u003easArray($type)])\n@endforeach\n```\n\nThe partial will contain the same templates as the previous examples, but this time, notice the difference between the `name`, `id` and `error` key:\n\n```blade\n\u003cinput name=\"client_address[billing]\" id=\"client_address_billing\" value=\"\"\u003e\n\n@error('client_address.billing')\n    {{ $message }}\n@enderror\n```\n\nAlternatively, you can also use the field name as the array key, by not specifying a key in advance:\n\n```blade\n@include('forms.address', ['prefixer' =\u003e FormFieldPrefixer::make('client')-\u003easArray()])\n```\n\nNow the `address` field will look like this:\n\n```blade\n\u003cinput name=\"client[address]\" id=\"client_address\" value=\"\"\u003e\n\n@error('client.address')\n    {{ $message }}\n@enderror\n```\n\nAgain, if you did not specify a prefix, `client_` would be stripped off.\n\n### Multi Dimensional Array Forms\n\nYou can also use a multi dimensional array notation. For this, you always need to specify a prefix, as that will be the basename of the input. If you don't, the result will be a flat array like in the previous example.\n\n```blade\n@foreach(['billing', 'shipping'] as $type)\n    @include('forms.address', ['prefixer' =\u003e FormFieldPrefixer::make('client')-\u003easMultiDimensionalArray($type)])\n@endforeach\n```\n\nThe partial will contain the same templates as the previous examples, but this time, notice that the input's name is now an array key.\n\n```blade\n\u003cinput name=\"client[billing][address]\" id=\"client_billing_address\" value=\"\"\u003e\n\n@error('client.billing.address')\n    {{ $message }}\n@enderror\n```\n\n### Hybrid Forms with a Touch of VueJS\n\n_**Disclaimer:** As a backend kind of guy, I didn't want to go all-in on JS, but I wanted to add just enough JS to make things work. I'm using VueJS, so this solution will only work with VueJS at this time. Making PHP and VueJS work together nicely with these dynamic forms was much more tricky than I thought (attributes needed much manipulation). But because I didn't want to duplicate all of my forms, I kept banging my head against the keyboard until this package fell out. So far I'm pretty happy with the working result._\n\nThis code is supported, but not included in this package because it is project specific.\n\nFeel free to copy the example and adjust it as you need.\n\n**Again, this is a very minimal example, just enough to make things work!**\n\n#### Example Use Case\n\nLet's say we are adding and removing form fields dynamically when someone clicks a button. For each fictional \"client\" that we add, we require the included form fields to be filled in.\n\nWe need data binding to keep the form fields in sync when we add and remove them. When we get validation errors upon submission, we also need to restore any previously dynamically added fields with their filled in \"old input\".\n\n#### Extra Setup\n\nTo get this to work, we need some sort of JS \"form manager\" that indexes the added clients and keeps a record of all of their input data. Let's create a Vue component that will do this:\n\n```js\n/* components/FormManager.vue */\n\u003cscript\u003e\nexport default {\n    props: {\n        values: { required: true },\n        errors: { required: true },\n    },\n\n    data() {\n        return {\n            formValues: [],\n            formErrors: [],\n        }\n    },\n\n    mounted() {\n        this.formValues = this.values\n        this.formErrors = this.errors\n    },\n\n    methods: {\n        add() {\n            this.formValues.push({})\n        },\n\n        remove(index) {\n            this.formValues.splice(index, 1)\n            this.formErrors = []\n        },\n\n        getError(key) {\n            return (this.formErrors[key] || [])[0]\n        }\n    },\n\n    render() {\n        return this.$scopedSlots.default({\n            formValues: this.formValues,\n            addFormEntry: this.add,\n            removeFormEntry: this.remove,\n            getError: this.getError,\n        })\n    },\n}\n\u003c/script\u003e\n```\n\nDon't forget to register the component in your `app.js` file:\n\n```js\n/* app.js */\nwindow.Vue = require('vue');\n\nVue.component('form-manager', require('./components/FormManager').default);\n\nconst app = new Vue({\n    el: '#app',\n});\n```\n\n#### Using the Form Manager\n\nLet's wrap our dynamic form parts with this new component. We also need to feed it any \"old input\" and validation errors, in case we get redirected back after the form submission fails.\n\n```blade\n\u003cform-manager\n    :values=\"{{ json_encode(old('clients', [])) }}\"\n    :errors=\"{{ json_encode($errors-\u003egetMessages()) }}\"\n    v-slot:default=\"{ formValues: clients, addFormEntry, removeFormEntry, getError }\"\n\u003e\n\t\u003cdiv v-for=\"(client, index) in clients\" :key=\"index\"\u003e\n\t    \u003ch2\u003eClient #@{{ index + 1 }}\u003c/h2\u003e\n\t    \n\t    @include('forms.address', ['prefixer' =\u003e FormFieldPrefixer::make('clients')-\u003easMultiDimensionalArray('${ index || 0 }')])\n\t    \n\t    \u003cbutton type=\"button\" @click=\"removeFormEntry(index)\"\u003e\n\t        Remove Client\n\t    \u003c/button\u003e\n\t\u003c/div\u003e\n\t\n\t\u003cbutton type=\"button\" @click=\"addFormEntry()\"\u003e\n\t    Add Client\n\t\u003c/button\u003e\n\u003c/form-manager\u003e\n```\n\n**What we are doing here is:**\n\n- we are feeding the `form-manager` any old `clients` input values in JSON format\n- we are also feeding the `form-manager` the `errors` array in JSON format\n- we use a scoped slot to access and bind the feeded `formValues` using the `clients` alias\n- we use a scoped slot to access the  `addFormEntry`, `removeFormEntry` and `getError` methods\n- we are using a prefix of `clients` with the `FormFieldPrefixer` \n- we are using a JS string as multi dimensional array key which will eventually print the array index\n- `clients` will be the basename of the multi dimensional array\n- this package will use the `clients` prefix as variable name to generate input bindings\n- **the `formValues` alias should be the same as the `FormFieldPrefixer` prefix**\n- we add a button to add and remove a set of client form fields\n- the `client` variable from the for loop is not used in this example\n\n#### Template Enhancements\n\nTo use the form field templates with both PHP and JS, you need to add one thing to your select fields:\n\n```blade\n\u003cselect\n    {{ $prefixer-\u003ename('title') }}\n    {{ $prefixer-\u003eid('title') }}\n    {{ $prefixer-\u003eselect('title') /* Add this line for JS compatibility */ }}\n\u003e\n    @foreach(['Mr.', 'Mrs.'] as $option)\n        \u003coption value=\"{{ $option }}\" {{ $prefixer-\u003eselected('title', $option, 'Mr.') }}\u003e\n            {{ $option }}\n        \u003c/option\u003e\n    @endforeach\n\u003c/select\u003e\n```\n\nThis will compile to:\n\n```blade\n\u003cselect\n    :name=\"`clients[${ index || 0 }][title]`\"\n    :id=\"`clients_${ index || 0 }_title`\"\n    v-model=\"clients[index || 0]['title']\"\n\u003e\n    \u003coption value=\"mr\"\u003eMr.\u003c/option\u003e\n    \u003coption value=\"mrs\"\u003eMrs.\u003c/option\u003e\n\u003c/select\u003e\n```\n\nNotice that instead of a `selected` attribute on an option, there is now a `v-model` attribute on the select.\n\nWhen you use the same template in a partial that does not have any JS key passed to it, the `v-model` will not be rendered and the `selected` attribute will. So you can use this \"enhanced\" template for all use cases.\n\n**The other form field templates do not need to be changed.**\n\nText inputs will automatically get a `v-model` attribute instead of a `value` attribute.\n\n#### Default Values are Ignored\n\nIf you want to load default values in your JS-driven form fields when the page loads, you will need to feed those values to the `form-manager`, in the same way you feed it the \"old input\".\n\nAny default values passed to the `FormFieldPrefixer` methods are ignored when using JS keys.\n\n#### Validation Errors\n\nI ended up extracting a form error partial:\n\n```blade\n@php $prefixer = $prefixer ?? FormFieldPrefixer::make(); @endphp\n\n{!!-- For JS enabled fields that render client side... --!!}\n@if ($prefixer-\u003eisJavaScript())\n    \u003cdiv v-show=\"!!getError({{ $prefixer-\u003evalidationKey($field) }})\"\u003e\n        \u003cdiv v-text=\"getError({{ $prefixer-\u003evalidationKey($field) }})\"\u003e\u003c/div\u003e\n    \u003c/div\u003e\n@endif\n\n{!!-- For normal fields that render server side... --!!}\n@error($prefixer-\u003evalidationKey($field))\n    \u003cdiv\u003e{{ $message }}\u003c/div\u003e\n@enderror\n```\n\nThen just include it...\n\n```blade\n@include('partials.form-error', ['field' =\u003e 'field_name'])\n```\n\n#### Browser Compatibility (JS)\n\nWorks with all modern browsers, except Internet Explorer, because it uses template strings:\n\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals\n\n### Modify or Remove the Attribute Name\n\nIf you only want the attribute's value, without its name and the quotes, you can pass `null` as a second parameter to the `name`, `id` and `for` method, or as a third parameter to the `value` method.\n\n```blade\n\u003cinput name=\"{{ $prefixer-\u003ename('some_field', null) }}\"\u003e // will echo: some_field\n```\n\nYou can also specify a different attribute name:\n\n```blade\n\u003clabel {{ $prefixer-\u003eid('some_field', 'for') }}\u003e // will echo: for=\"some_field\"\n```\n\n### Provide a Fallback FormFieldPrefixer\n\nIf you want to be able to use your partials even without passing it a `FormFieldPrefixer` instance, you could add the following snippet to the top of you partials:\n\n```blade\n@php $prefixer = $prefixer ?? FormFieldPrefixer::make(); @endphp\n```\n\nThis will make sure there is always a `$prefixer` variable available.\n\nOf course, you are free to choose another variable name.\n\n## 🚧 Testing\n\n```bash\ncomposer test\n```\n\n## ☕️ Credits\n\n- [Ivan Vermeyen](https://byterider.io)\n- [All contributors](../../contributors)\n\n## 🔓 Security\n\nIf you discover any security related issues, please [e-mail me](mailto:ivan@codezero.be) instead of using the issue tracker.\n\n## 📑 Changelog\n\nSee a list of important changes in the [changelog](CHANGELOG.md).\n\n## 📜 License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodezero-be%2Flaravel-form-field-prefixer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodezero-be%2Flaravel-form-field-prefixer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodezero-be%2Flaravel-form-field-prefixer/lists"}