{"id":17148657,"url":"https://github.com/lcharette/uf_formgenerator","last_synced_at":"2025-06-11T04:33:33.168Z","repository":{"id":57013034,"uuid":"68563337","full_name":"lcharette/UF_FormGenerator","owner":"lcharette","description":"Form Generator sprinkle for Userfrosting 5","archived":false,"fork":false,"pushed_at":"2024-04-02T01:11:48.000Z","size":1645,"stargazers_count":17,"open_issues_count":4,"forks_count":4,"subscribers_count":3,"default_branch":"5.1","last_synced_at":"2024-11-04T07:38:23.482Z","etag":null,"topics":["userfrosting","userfrosting-sprinkle"],"latest_commit_sha":null,"homepage":"","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/lcharette.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"lcharette","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2016-09-19T02:51:24.000Z","updated_at":"2024-06-24T16:40:08.000Z","dependencies_parsed_at":"2024-01-12T06:52:57.885Z","dependency_job_id":"dcc55f4b-b2c2-468b-9275-446852d012dd","html_url":"https://github.com/lcharette/UF_FormGenerator","commit_stats":{"total_commits":142,"total_committers":6,"mean_commits":"23.666666666666668","dds":"0.11267605633802813","last_synced_commit":"358a6c5b25c41dd7a77883024c4a7d3b7cf55754"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcharette%2FUF_FormGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcharette%2FUF_FormGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcharette%2FUF_FormGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lcharette%2FUF_FormGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lcharette","download_url":"https://codeload.github.com/lcharette/UF_FormGenerator/tar.gz/refs/heads/5.1","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223581935,"owners_count":17168655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["userfrosting","userfrosting-sprinkle"],"created_at":"2024-10-14T21:29:26.263Z","updated_at":"2024-11-07T20:04:53.161Z","avatar_url":"https://github.com/lcharette.png","language":"PHP","funding_links":["https://ko-fi.com/lcharette","https://ko-fi.com/A7052ICP"],"categories":[],"sub_categories":[],"readme":"# Form Generator Sprinkle for [UserFrosting 5](https://www.userfrosting.com)\n\n[![Donate][kofi-badge]][kofi]\n[![Latest Version][releases-badge]][releases]\n[![UserFrosting Version][uf-version]][uf]\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)\n[![Build][build-badge]][build]\n[![PHPStan][PHPStan-badge]][PHPStan]\n[![Codecov][codecov-badge]][codecov]\n[![StyleCI][styleci-badge]][styleci]\n\n[kofi]: https://ko-fi.com/A7052ICP\n[kofi-badge]: https://img.shields.io/badge/Donate-Buy%20Me%20a%20Coffee-blue?logo=ko-fi\u0026logoColor=white\n[releases]: https://github.com/lcharette/UF_FormGenerator/releases\n[releases-badge]: https://img.shields.io/github/release/lcharette/UF_FormGenerator.svg\n[uf-version]: https://img.shields.io/badge/UserFrosting-\u003e=%205.0-brightgreen.svg\n[uf]: https://github.com/userfrosting/UserFrosting\n[build]: https://github.com/lcharette/UF_FormGenerator/actions?query=workflow%3ABuild\n[build-badge]: https://img.shields.io/github/actions/workflow/status/lcharette/UF_FormGenerator/Build.yml?branch=5.0\u0026logo=github\n[PHPStan]: https://github.com/lcharette/UF_FormGenerator/actions?query=workflow%3APHPStan\n[PHPStan-badge]: https://img.shields.io/github/actions/workflow/status/lcharette/UF_FormGenerator/PHPStan.yml?branch=5.0\u0026label=PHPStan\n[codecov]: https://codecov.io/gh/lcharette/UF_FormGenerator\n[codecov-badge]: https://codecov.io/gh/lcharette/UF_FormGenerator/branch/5.0/graph/badge.svg\n[styleci]: https://styleci.io/repos/68563337\n[styleci-badge]: https://styleci.io/repos/68563337/shield?branch=5.0\u0026style=flat\n\nThis Sprinkle provides helper classes, Twig template and JavaScript plugins to generate HTML forms, modals and confirm modal bases on UserFrosting [validation schemas](https://learn.userfrosting.com/routes-and-controllers/client-input/validation).\n\n# Help and Contributing\n\nIf you need help using this sprinkle or found any bug, feels free to open an issue or submit a pull request. You can also find me on the [UserFrosting Chat](https://chat.userfrosting.com/) most of the time for direct support.\n\n# Versions and UserFrosting support\n\n| UserFrosting Version | FormGenerator Version |\n| :------------------: | :-------------------: |\n|        5.1.x         |         5.1.x         |\n|        5.0.x         |         5.0.x         |\n|        4.4.x         |         4.x.x         |\n|        4.3.x         |    [3.0.x] \u0026 4.0.x    |\n|        4.2.x         |        [3.0.x]        |\n|        4.1.x         |        [2.0.x]        |\n|        4.0.x         |      No Support       |\n\n[3.0.x]: https://github.com/lcharette/UF_FormGenerator/tree/3.0#form-generator-sprinkle-for-userfrosting-4\n[2.0.x]: https://github.com/lcharette/UF_FormGenerator/tree/2.2#form-generator-sprinkle-for-userfrosting-4\n\n# Installation\nTo install FormGenerator in your sprinkle : \n\n1. Install FormGenerator through Composer:\n    ```\n    composer require lcharette/uf_formgenerator \"~5.1.0\"\n    ```\n\n2. Add `UserFrosting\\Sprinkle\\FormGenerator\\FormGenerator` to your Sprinkle Recipe sprinkle method. \n\n3. To use the frontend helper, first install the npm dependency:\n    ```\n    npm install --save @lcharette/formgenerator@~5.1.0\n    ```\n\n4. Then add this entry to your `webpack.config.js`, in the `sprinkles` list : \n    ```js\n    FormGenerator: require('@lcharette/formgenerator/webpack.entries'),\n    ```\n\n5. Each template file where you want to use the frontend helper, add this line to `{% block scripts_page %}`:\n    ```\n    {{ encore_entry_script_tags('widget.formGenerator') }}\n    ```\n\n6. Run `php bakery bake` to finish installation of the sprinkle.\n\nAlternatively, you can add `@lcharette/formgenerator/app/assets/js/widget-formGenerator.js` globally in your app main js file.\n\n# Working example\n\nThe `public/` directory serves as an example of FormGenerator. You can clone this repository and install as any UserFrosting 5 sprinkle :\n1. `composer install`\n2. `php bakery bake`\n3. `php -S localhost:8080 -t public`\n\nThis demo is not linked to any database tables, so changes are not actually saved ;)\n\n![Screenshot 1](/.github/screenshots/UF_FormGeneratorExample1.png?raw=true)\n![Screenshot 2](/.github/screenshots/UF_FormGeneratorExample2.png?raw=true)\n![Screenshot 3](/.github/screenshots/UF_FormGeneratorExample3.png?raw=true)\n![Screenshot 4](/.github/screenshots/UF_FormGeneratorExample4.png?raw=true)\n\n# Features and usage\nBefore starting with _FormGenerator_, you should read the main UserFrosting guide to familiarize yourself with _validation schemas_: (https://learn.userfrosting.com/routes-and-controllers/client-input/validation).\n\n## Form generation\n### Defining the fields in the schema\nThis sprinkle uses the `schemas` used by UserFrosting to validate form data to build form. To achieve this, a new `form` key is simply added to the fields found in a `schema` file.\n\nFor example, here's a simple `schema` used to validate a form used to create a `project`. The form will contain a `name`, `description` and `status` fields.\n\n```json\n{\n    \"name\" : {\n        \"validators\" : {\n            \"length\" : {\n                \"min\" : 1,\n                \"max\" : 100\n            },\n            \"required\" : {\n                \"message\" : \"PROJECT.VALIDATE.REQUIRED_NAME\"\n            }\n        }\n    },\n    \"description\" : {\n        \"validators\" : {}\n    },\n    \"status\" : {\n        \"validators\" : {\n            \"member_of\" : {\n                \"values\" : [\n                    \"0\", \"1\"\n                ]\n            },\n            \"required\" : {\n                \"message\" : \"PROJECT.VALIDATE.STATUS\"\n            }\n        }\n    }\n}\n```\n\u003e Note: FormGenerator works with json and YAML schemas.\n\nAt this point, with typical UserFrosting setup, you would be going into your controller and Twig files to manually create your HTML form. This can be easy if you have a two or three fields, but can be a pain with a dozen fields and more. This is where FormGenerator steps in with the use of a new `form` attribute. Let's add it to our `project` form :\n\n```json\n{\n    \"name\" : {\n        \"validators\" : {\n            \"length\" : {\n                \"min\" : 1,\n                \"max\" : 100\n            },\n            \"required\" : {\n                \"message\" : \"VALIDATE.REQUIRED_NAME\"\n            }\n        },\n        \"form\" : {\n            \"type\" : \"text\",\n            \"label\" : \"NAME\",\n            \"icon\" : \"fa-flag\",\n            \"placeholder\" : \"NAME\"\n        }\n    },\n    \"description\" : {\n        \"validators\" : {},\n        \"form\" : {\n            \"type\" : \"textarea\",\n            \"label\" : \"DESCRIPTION\",\n            \"icon\" : \"fa-pencil\",\n            \"placeholder\" : \"DESCRIPTION\",\n            \"rows\" : 5\n        }\n    },\n    \"status\" : {\n        \"validators\" : {\n            \"member_of\" : {\n                \"values\" : [\n                    \"0\", \"1\"\n                ]\n            },\n            \"required\" : {\n                \"message\" : \"VALIDATE.STATUS\"\n            }\n        },\n        \"form\" : {\n            \"type\" : \"select\",\n            \"label\" : \"STATUS\",\n            \"options\" : {\n                \"0\" : \"Active\",\n                \"1\" : \"Disabled\"\n            }\n        }\n    }\n}\n```\n\nLet's look closer at the `name` field :\n\n```json\n\"form\" : {\n    \"type\" : \"text\",\n    \"label\" : \"PROJECT.NAME\",\n    \"icon\" : \"fa-flag\",\n    \"placeholder\" : \"PROJECT.NAME\"\n}\n```\n\nHere you can see that we define the `type`, `label`, `icon` and `placeholder` value for this `name` field. You can define any standard [form attributes](http://www.w3schools.com/html/html_form_attributes.asp), plus the `icon`, `label` and `default` attributes. `data-*` attributes can also be defined in your schema if you need them. For the `select` element, a special `options` attribute containing an array of `key : value` can be used to define the dropdown options. The select options (as any other attributes) can also be set in PHP (see further below).\n\nAnd of course, the values of the `label` and `placeholder` attributes can be defined using _translation keys_.\n\nCurrently, FormGenerator supports the following form elements :\n- text (and any input supported by the HTML5 standard : number, tel, password, etc.)\n- textarea\n- select\n- checkbox\n- hidden\n- alert (Display a static alert box in the form)\n\n### The controller part\nOnce your fields defined in the `schema` json or yaml file, you need to load that schema in your controller.\n\nFirst thing to do is add FormGenerator's `Form` class to your \"use\" list :\n`use UserFrosting\\Sprinkle\\FormGenerator\\Form;`\n\nNext, where you load the schema and setup the `validator`, you simply add the new Form creation:\n```php\n// Load validator rules\n$schema = new RequestSchema(\"schema://project.json\");\n$validator = new JqueryValidationAdapter($schema, $this-\u003etranslator);\n\n// Create the form\n$form = new Form($schema, $project);\n```\n\nIn this example, `$project` can contain the default (or current value) of the fields. A data collection fetched from the database with eloquent can also be passed directly. That second argument can also be omitted to create an empty form.\n\nLast thing to do is send the fields to Twig. In the list of returned variables to the template, add the `fields` variable:\n```php\n$view-\u003erender($response, \"pages/myPage.html.twig\", [\n    \"fields\" =\u003e $form-\u003egenerate(),\n    \"validators\" =\u003e $validator-\u003erules('json', true)\n]);\n\n```\n\n### The Twig template part\n\nNow it's time to display the form in `myPage.html.twig` !\n\n```html\n\u003cform name=\"MyForm\" method=\"post\" action=\"/Path/to/Controller/Handling/Form\"\u003e\n    {% include \"forms/csrf.html.twig\" %}\n    \u003cdiv id=\"form-alerts\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"row\"\u003e\n        \u003cdiv class=\"col-sm-8\"\u003e\n            {% include 'FormGenerator/FormGenerator.html.twig' %}\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"row\"\u003e\n      \u003cbutton type=\"submit\" class=\"btn btn-block btn-lg btn-success\"\u003eSubmit\u003c/button\u003e\n    \u003c/div\u003e\n\u003c/form\u003e\n```\n\nThat's it! No need to list all the field manually. The ones defined in the `fields` variable will be displayed by `FormGenerator/FormGenerator.html.twig`. Note that this will only load the fields, not the form itself. The `\u003cform\u003e` tag and `submit` button needs to be added manually.\n\n## Modal form\nWhat if you want to show a form in a modal window? Well, FormGenerator makes it even easier! It's basically three steps:\n1. Setup your form schema (as described above)\n2. Setup the form in your controller\n3. Call the modal from your template\n\n### Setup the form in your controller\nWith your schema in hand, it's time to create a controller and route to load your modal. The controller code will be like any basic UserFrosting modal, plus the `$form` part above and one changes in the `render` part. For example :\n\n```php\n$view-\u003erender($response, \"FormGenerator/modal.html.twig\", [\n    \"box_id\"        =\u003e $get['box_id'],\n    \"box_title\"     =\u003e \"PROJECT.CREATE\",\n    \"submit_button\" =\u003e \"CREATE\",\n    \"form_action\"   =\u003e '/project/create',\n    \"fields\"        =\u003e $form-\u003egenerate(),\n    \"validators\"    =\u003e $validator-\u003erules('json', true)\n]);\n```\n\nAs you can see, instead of rendering your own Twig template, you simply have to specify FormGenerator's modal template. This template requires the following variables:\n1. `box_id`: This should always be `$get['box_id']`. This is used by the JavaScript code to actually display the modal.\n2. `box_title`: The title of the modal.\n3. `submit_button`: The label of the submit button. Optional. Default to `SUBMIT` (localized).\n4. `form_action`: The route where the form will be sent\n5. `fields`: The fields. Should always be `$form-\u003egenerate()`\n6. `validators`: Client side validators\n\n### Call the modal from your template\nSo at this point you have a controller that displays the modal at a `/path/to/controller` route. Time to show that modal. Again, two steps:\n\nFirst, define a link or a button that will call the modal when clicked. For example :\n```html\n\u003cbutton class=\"btn btn-success js-displayForm\" data-formUrl=\"/path/to/controller\"\u003eCreate\u003c/button\u003e\n```\n\nThe important part here is the `data-formUrl` attribute. This is the route that will load your form. `js-displayForm` is used here to bind the button to the action.\n\nSecond, load the FormGenerator JavaScript widget. Add this to your Twig file:\n```\n{% block scripts_page %}\n    {{ assets.js('js/FormGenerator') | raw }}\n{% endblock %}\n```\n\nBy default, the `formGenerator` plugin will bind a **form modal** to every element with the `js-displayForm` class.\n\n## Modal confirmation\n\nOne side features of FormGenerator is the ability to add a confirmation modal to your pages with simple HTML5 attributes. The process is similar to adding a modal form, without the need to create any controller or route.\n\nLet's look at a delete button / confirmation for our `project` :\n```html\n\u003ca href=\"#\" class=\"btn btn-danger js-displayConfirm\"\n  data-confirm-title=\"Delete project ?\"\n  data-confirm-message=\"Are you sure you want to delete this project?\"\n  data-confirm-button=\"Yes, delete project\"\n  data-post-url=\"/project/delete\"\u003e\u003ci class=\"fa fa-trash-o\"\u003e\u003c/i\u003e Delete\u003c/a\u003e\n```\n(Note that content of data attributes can be translation keys)\n\nIf not already done, make sure the FormGenerator assets are included in your template.\n```\n{% block scripts_page %}\n    {{ assets.js('js/FormGenerator') | raw }}\n{% endblock %}\n```\n\nBy default, the `formGenerator` plugin will bind a **confirmation modal** to every element with the `js-displayConfirm` class.\n\n## Advance usage\n\n### Defining attributes in PHP\n\n#### setInputArgument\n\nForm field input attributes can also be added or edited from PHP. This can be useful when dynamically defining a Select input options. To do this, simply use the `setInputArgument($inputName, $property, $data)` method. For example, to add a list to a `clients` select :\n\n```php\n// Get clients from the db model\n$clients = Clients::all();\n\n$form = new Form($schema);\n$form-\u003esetInputArgument('clients', 'options', $clients);\n```\n\n#### setData\n\nIf you want to set the form values once the form instance is created, you can use the `setData($data)` method:\n\n```php\n$form = new Form($schema);\n$form-\u003esetData($clients, $project);\n```\n\n#### setValue\n\nSimilar to the `setData` method, you can set a specific input value using the `setValue($inputName, $value)` method :\n\n```php\n$currentClient = ...\n\n$form = new Form($schema, $project);\n$form-\u003esetValue('clients', $currentClient);\n```\n\n#### setFormNamespace\n\nWhen dealing with multiple form on the same page or a dynamic number of input (you can use the new `Loader` system in 4.1 to build dynamic schemas!), it can be useful to wrap form elements in an array using the `setFormNamespace($namespace)` method. This can also your the input names [to contains dot syntaxt](http://stackoverflow.com/a/20365198/445757).\n\nFor example, `$form-\u003esetFormNamespace(\"data\");` will transform all the input names from `\u003cinput name=\"foo\" [...] /\u003e` to `\u003cinput name=\"data[foo]\" [...] /\u003e`.\n\n#### registerType\n\nIf you want to overwrite or add a new element type,\n\n\nFirst, you need to create the element itself. This class needs to extends the `UserFrosting\\Sprinkle\\FormGenerator\\Element\\Input` class. In there you can define the default attributes, and do other transformation. For example, to define a new `Date` element type :\n\n```php\n\u003c?php\n\nnamespace UserFrosting\\Sprinkle\\MySprinkle\\Element;\n\nuse UserFrosting\\Sprinkle\\FormGenerator\\Element\\Input;\n\nclass Date extends Input\n{\n    protected function applyTransformations(): void\n    {\n        $this-\u003eelement = array_merge([\n            'class' =\u003e 'myDateElement',\n            'value' =\u003e $this-\u003egetValue(),\n            'name'  =\u003e $this-\u003ename,\n            'id'    =\u003e 'field_' . $this-\u003ename,\n            'date-foo' =\u003e //...\n        ], $this-\u003eelement);\n    }\n}\n```\n\nNext, you need to register your `Date` element type. If the `date` type is already registered, it will be overwritten by your custom class.\n\n```php\n$form = new Form($schema, $project);\n$form-\u003eregisterType('date', UserFrosting\\Sprinkle\\MySprinkle\\Element\\Date::class);\n```\n\n### Javascript Plugin\n\nBy default, the `formGenerator` plugin will bind a **form modal** to every element with the `js-displayForm` class and will bind a **confirmation modal** to every element with the `js-displayConfirm` class. You can\n\n#### Options\nThe following options are available:\n\nJust pass an object with those\n - `mainAlertElement` (jQuery element). The element on the main page where the main alerts will be displayed. Default to `$('#alerts-page')`.\n - `redirectAfterSuccess` (bool). If set to true, the page will reload when the form submission or confirmation is successful. Default to `true`.\n\nExample:\n```js\n$(\".project-edit-button\").formGenerator({redirectAfterSuccess: false});\n```\n\n#### Events\nYou can listen for some events returned by FormGenerator. Those events can be used to apply some actions when the modal is displayed or the form is successfully sent. For example, this is can be used with `redirectAfterSuccess` on `false` to refresh the data on the page when the form is submitted successfully.\n\n- `formSuccess.formGenerator`\n- `displayForm.formGenerator`\n- `displayConfirmation.formGenerator`\n- `confirmSuccess.formGenerator`\n- `error.formGenerator`\n\nExample:\n```js\n$(\".project-edit-button\").on(\"formSuccess.formGenerator\", function () {\n    // Refresh data\n});\n```\n\n# Running tests\n\nFormGenerator comes with some unit tests. Before submitting a new Pull Request, you need to make sure all tests are a go. With the sprinkle added to your UserFrosting installation, simply execute the `php bakery test FormGenerator` command to run the tests.\n\n# License\n\nBy [Louis Charette](https://bbqsoftwares.com). Copyright (c) 2020, free to use in personal and commercial software as per the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flcharette%2Fuf_formgenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flcharette%2Fuf_formgenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flcharette%2Fuf_formgenerator/lists"}