{"id":20961849,"url":"https://github.com/heimrichhannot/contao-form-type-bundle","last_synced_at":"2026-03-10T12:30:44.103Z","repository":{"id":191415340,"uuid":"684606497","full_name":"heimrichhannot/contao-form-type-bundle","owner":"heimrichhannot","description":"Define form generator types to customize forms.","archived":false,"fork":false,"pushed_at":"2026-02-02T16:58:44.000Z","size":99,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-02-03T06:07:35.013Z","etag":null,"topics":["contao","contao5","forms"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/heimrichhannot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"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}},"created_at":"2023-08-29T13:36:59.000Z","updated_at":"2025-12-11T12:52:08.000Z","dependencies_parsed_at":"2023-08-29T21:13:55.331Z","dependency_job_id":"fdd8b5a5-6090-4d67-b52b-d6132b0ec89a","html_url":"https://github.com/heimrichhannot/contao-form-type-bundle","commit_stats":null,"previous_names":["heimrichhannot/contao-formgenerator-type-bundle","heimrichhannot/contao-form-type-bundle"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/heimrichhannot/contao-form-type-bundle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-form-type-bundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-form-type-bundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-form-type-bundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-form-type-bundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/heimrichhannot","download_url":"https://codeload.github.com/heimrichhannot/contao-form-type-bundle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heimrichhannot%2Fcontao-form-type-bundle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30333423,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"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":["contao","contao5","forms"],"created_at":"2024-11-19T02:17:54.546Z","updated_at":"2026-03-10T12:30:44.085Z","avatar_url":"https://github.com/heimrichhannot.png","language":"PHP","readme":"# Form Type Bundle\n\nForm type bundle is an extension for the Contao CMS to provide a generic way to create forms for specific approaches with contao form generator. \nIt is aimed at developers and contains no build-in form types.\n\n## Feature\n* Generic way to create forms for specific approaches with contao form generator\n* Options event for select, checkbox and radio form fields\n* Form types can support a first time wizard to setup basic form fields\n\n## Installation\n\nInstall the bundle via composer and update your database afterwards:\n\n```\ncomposer require heimrichhannot/contao-form-type-bundle\n```\n\n## Usage\n\n### Create a new form type\n\nCreate a new class that extends `AbstractFormType`. Register it as service with autoconfiguration enabled.\n\nA label can be set within `$GLOBALS['TL_LANG']['tl_form']['FORMTYPE']`:\n\n```php\n# contao/languages/de/tl_form.php\n$GLOBALS['TL_LANG']['tl_form']['FORMTYPE']['huh_mediathek'] = 'Mediathek';\n```\n\n### First time wizard\n\nYou can add a first time wizard to your form type by implementing `getDefaultFields()` method.\nIt expects field definitions in array format as return values. \nThese fields will be created when executing the wizard.\n\n```php\npublic function getDefaultFields(FormModel $formModel): array\n{\n    return [\n        [\n            'type' =\u003e 'text',\n            'name' =\u003e 'title',\n            'label' =\u003e $this-\u003etranslator-\u003etrans('tl_example.title.0', [], 'contao_tl_example'),\n            'mandatory' =\u003e '1',\n        ],\n        [\n            'type' =\u003e 'textarea',\n            'name' =\u003e 'text',\n            'label' =\u003e $this-\u003etranslator-\u003etrans('tl_example.text.0', [], 'contao_tl_example'),\n        ],\n    ];\n}\n```\n\n### Form events\n\nYou can register event listeners for events during form livecycle.\nThese events are mappings of the corresponding contao form hooks but will only fire for the specific form type.\n\nFollowing events are available:\n\n| Event                  | Name                                     |\n|------------------------|------------------------------------------|\n| CompileFormFieldsEvent | huh.form_type.[TYPE].compile_form_fields |\n| LoadFormFieldEvent     | huh.form_type.[TYPE].load_form_field     |\n| PrepareFormDataEvent   | huh.form_type.[TYPE].prepare_form_data   |\n| ProcessFormDataEvent   | huh.form_type.[TYPE].process_form_data   |\n| StoreFormDataEvent     | huh.form_type.[TYPE].store_form_data     |\n| ValidateFormFieldEvent | huh.form_type.[TYPE].validate_form_field |\n\n\n### Options event\n\nIf you want to provide options for a select, checkbox or radio form field, you can register an event listener. \nThe event name is `huh.form_type.\u003cformtype\u003e.\u003cfield\u003e.options'`.\n\n```php\n// src/EventListener/OptionsEventListener.php\nuse HeimrichHannot\\FormTypeBundle\\Event\\FieldOptionsEvent;\n\nclass OptionsEventListener implements EventSubscriberInterface\n{\n    public static function getSubscribedEvents()\n    {\n        return [\n            'huh.form_type.huh_media_library.licence.options' =\u003e 'onLicenceOptions',\n        ];\n    }\n\n    public function onLicenceOptions(FieldOptionsEvent $event): void\n    {\n        $event-\u003eaddOption('free', 'Free');\n        $event-\u003eaddOption('adobe', 'Adobe');\n        $event-\u003eaddOption('istock', 'iStock');\n    }\n    \n    public function onTopicOptions(FieldOptionsEvent $event): void\n    {\n        $event-\u003eaddOption('cinema', 'Cinema', 'entertainment');\n        $event-\u003eaddOption('music', 'Music', 'entertainment');\n        \n        $event-\u003eaddOption('politics', 'Politics', 'news');\n        $event-\u003eaddOption('sport', 'Sport', 'news');\n        $event-\u003eaddOption('culture', 'Culture', 'news');\n    }\n}\n```\n\n#### Unified Dispatcher for Field Options\n\nUse `FieldOptionsDispatcherTrait` to dispatch `FieldOptionsEvent` `huh.form_type.\u003cformtype\u003e.\u003cfield\u003e.options` and Contao `fields.\u003cfield\u003e.options` callbacks alike.\n\n\nExample:\n```php\nuse HeimrichHannot\\MediaLibraryBundle\\Trait\\FieldOptionsDispatcherTrait;\n\nclass MyContainerOrFormType\n{\n    use FieldOptionsDispatcherTrait;\n\n    #[AsCallback(table: 'tl_ml_product', target: 'fields.licence.options')]\n    #[AsEventListener('huh.form_type.huh_media_library.licence.options')]\n    public function getLicenceOptions(): array\n    {\n        return $this-\u003edispatchFieldOptions([\n            'free' =\u003e 'Released for use under indication of copyright',\n            'locked' =\u003e 'Subject to licence'\n        ]);\n    }\n}\n```\n\n### Get form options\n\nUse the `FormTypeCollection` class to get form options to use in your dca fields or wherever you need them.\n\n```php\nuse Contao\\CoreBundle\\DependencyInjection\\Attribute\\AsCallback;\nuse HeimrichHannot\\EventRegistrationBundle\\FormType\\EventRegistrationFormType;\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormTypeCollection;\n\n#[AsCallback(table: 'tl_calendar', target: 'fields.reg_form.options')]\nclass FieldsRegFormOptionsListener\n{\n    private readonly FormTypeCollection $formTypeCollection,\n\n    public function __invoke(): array\n    {\n        return $this-\u003eformTypeCollection-\u003egetFormsForFormType(EventRegistrationFormType::TYPE);\n    }\n}\n```\n\n### Form Context\n\nImplementing a form context evaluator on your from type allows you to change the form's behavior depending on the context it is used in.\nThis can be used e.g. to load existing data into the form fields, perhaps to create an editing form.\n\n#### Built-in Form Edit Context\n\nA basic default form context evaluator providing editing functionality is built into the bundle.\nJust override `DEFAULT_FORM_CONTEXT_TABLE` in your form type to allow editing the respective database model:\n```php\nprotected const DEFAULT_FORM_CONTEXT_TABLE = 'tl_my_table';\n```\n\n* Create your form in Contao.\n* Name your form fields like the database fields you want to edit, e.g. `title` for `tl_my_table.title`.\n* Append the query parameter `?edit=\u003cid\u003e` to the url of the page your form is included in to edit the existing row with a primary key of `\u003cid\u003e`.\n\nIf no `DEFAULT_FORM_CONTEXT_TABLE` is set, the form will be treated as a creation form by default.\n\n#### Create your own Form Context\n\nTo implement your own form context evaluator, override `evaluateFormContext()` in your form type:\n```php\nprotected function evaluateFormContext(): FormContext\n{\n    $request = $this-\u003econtainer-\u003eget('request_stack')-\u003egetCurrentRequest();\n    $editParameter = 'edit';\n    $databaseTable = 'tl_my_table';\n\n    if ($modelPk = $request-\u003equery-\u003eget($editParameter))\n    {\n        /** @var class-string\u003cModel\u003e $modelClass */\n        $modelClass = Model::getClassFromTable($databaseTable);\n        $modelInstance = $modelClass::findByPk($modelPk);\n        if ($modelInstance === null) {\n            return FormContext::invalid($databaseTable, 'Could not find object.');\n        }\n        return FormContext::update($databaseTable, $modelInstance-\u003erow());\n    }\n\n    return FormContext::create($databaseTable);\n}\n```\n\nThe example shows the implementation of a form context evaluator that allows editing a database model with a primary key given by the query parameter `edit`.\n\nTo retrieve the current form context, call the getter on your form type:\n```php\n$formContext = $this-\u003egetFormContext();\n```\n\nWe do not recommend to call `$this-\u003eevaluateFormContext()` directly, as it will skip future cache implementations if you do.\n\n#### Form Context Actions\n\nMost commonly used form context actions are already implemented.\n\n```php\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormContextAction;\n\nFormContextAction::CREATE;\nFormContextAction::READ;\nFormContextAction::UPDATE;\nFormContextAction::DELETE;\nFormContextAction::CLONE;\nFormContextAction::INVALID;\n```\n\n`FormContextAction::INVALID` can be used to indicate that the form should not be processed.\n\nTo instantiate a `FormContext` object with a built-in action, use the static factory methods:\n\n```php\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormContext;\n\n$createContext  = FormContext::create('tl_my_table');\n$readContext    = FormContext::read('tl_my_table', $data);\n$updateContext  = FormContext::update('tl_my_table', $data);\n$deleteContext  = FormContext::delete('tl_my_table', $data);\n\n$cloneContext   = FormContext::clone('tl_my_table', $data);\n\n$invalidContext = FormContext::invalid('tl_my_table', 'This is error detail.', $additionalData ?? []);\n```\n\nAlternatively, you may also use the `FormContext` constructor:\n\n```php\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormContext;\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormContextAction;\n\n$formContext = new FormContext(FormContextAction::UPDATE, 'tl_my_table', $data);\n```\n\n\nHowever, you may also specify your own actions when constructing a `FormContext` object, or by overriding the action of an existing object.\n\n```php\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormContext;\nuse HeimrichHannot\\FormTypeBundle\\FormType\\FormContextAction;\n\n$formContext = new FormContext('my_custom_action', 'tl_my_table', $data);\n// or\n$formContext-\u003esetAction('this_can_be_any_string_or_action');\n// or\n$formContext-\u003esetAction(FormContextAction::DELETE);\n```\n\nThis way you are not bound to the built-in actions.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheimrichhannot%2Fcontao-form-type-bundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fheimrichhannot%2Fcontao-form-type-bundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheimrichhannot%2Fcontao-form-type-bundle/lists"}