Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Form Extensions Bundle Laravel Package

symfony2admingenerator/form-extensions-bundle

Symfony bundle that extends the Symfony2 Admin Generator with extra form types, widgets and field extensions, making it easier to build richer admin forms with nested collections, uploads and other common backend needs.

View on GitHub
Deep Wiki
Context7

Getting Started

Check compatibility against the 4.x line, not the README. The project is now shipping v4.1.2, so the ~1.0 constraint you may have seen in older docs/blog posts is stale. Start with composer.json in the tag you intend to install: read the require block for the Symfony range, PHP floor, and Twig version. The v4.1.2 patch ("Fix reference to deprecated Extension class") is a signal in itself — it means the bundle's DI extension now extends the non-deprecated base, which only matters on Symfony 5.1+. Treat the 4.x line as the "modern" branch and the 1.x/2.x tags as the Admingenerator-era reference implementation.

A useful rule of thumb: if you are on Symfony 2.x/3.x, you want the old tags and the old AppKernel/Assetic instructions. If you are on Symfony 5.4/6.x, the 4.x line is your entry point — but verify the require block before assuming it is supported, because the changelog is one line and tells you nothing about the supported matrix.

Install:

composer require symfony2admingenerator/form-extensions-bundle:^4.1

Pin the minor. Do not use dev-master — with a project this small, master can drift to a commit expecting a Symfony version you do not have, and there will not be a release note warning you.

Register the bundle in config/bundles.php on Symfony 4+ (Symfony2admingenerator\FormExtensionsBundle\FormExtensionsBundle::class => ['all' => true]). Confirm the class name against the file in the repo root; the namespace casing (Symfony2admingenerator) is legacy and easy to get wrong.

Register the form types as services. On Symfony 5+, string aliases are gone — every type you use must either be a service tagged form.type or be referenced by FQCN. Check Resources/config/*.xml for whether the bundle tags its own types (it does, historically) and whether the tags survive into your installed version. If a widget renders but the field throws "could not load type", this is the cause.

Where to look first, in this order:

  1. Form/Type/ — the authoritative list of what you get: double list, upload/image, date/time pickers, WYSIWYG (CKEditor/TinyMCE/MarkItUp), elFinder, file-upload collections, AJAX autocomplete.
  2. Resources/config/*.xml — the exact aliases (double_list, upload, image, ckeditor, date_picker, datetime_picker, fileupload, autocomplete, elFinder, …) and the options each declares. Do not guess option names from the README; configureOptions() is the source of truth.
  3. Resources/views/Form/ — the layouts. This is where you will spend most of your time overriding.

First use case — replace a dull multi-select with the double list:

$builder->add('roles', DoubleListType::class, [
    'choices'  => $roleChoices,
    'multiple' => true,
    'attr'     => ['class' => 'col-md-6'],
]);

Then immediately verify the value round-trips: the widget posts a hidden input with the ordered selection, and re-rendering on validation failure is the first thing that breaks.

Implementation Patterns

Use it as a "widget catalogue", not a black box. The value is the Twig + JS glue for widgets Symfony doesn't ship natively. Adopt it field-by-field; do not retrofit your whole app to its conventions.

Upgrades within 4.x are cheap. v4.1.2 is a single-line DI fix with no API surface change — no form type options, templates, or aliases moved. Treat patch releases here as low-risk bumps: run your form smoke tests (render, submit, validation-failure re-render) and you are done. The real upgrade risk in this package lives in minor/major bumps and in Symfony upgrades, not in patches.

Pattern: double list for roles / permissions / tags. Best when order matters or the candidate set is too large for <select multiple>. Pair with a PRE_SUBMIT/POST_SUBMIT listener if you must normalise the array (e.g. strings → entity IDs). For a Doctrine collection, add a ModelTransformer — the type only transports strings.

Pattern: upload / image with lifecycle handling. The upload types render input plus preview/delete UI; they persist nothing.

  1. Add an unmapped field ('mapped' => false).
  2. In a prePersist/preUpdate Doctrine listener (or the controller), move the file out of upload_dir/upload_tmp_dir.
  3. Store the relative path on the entity.
  4. On delete, unlink the previous file yourself — the delete checkbox only records intent.
$builder->add('attachment', FileUploadType::class, [
    'mapped'     => false,
    'upload_dir' => 'uploads/documents',   // verify key against the type
    'max_size'   => '8M',
]);

Pattern: rich text (CKEditor / TinyMCE / MarkItUp). Configure the toolbar/profile once via bundle config, then add the type per field. Sanitise on render — these types store raw HTML; run HTMLPurifier (or equivalent) in your output layer, not in the form.

Pattern: AJAX autocomplete for large entity sets. The autocomplete family expects a JSON endpoint returning objects with id and a display label.

  • Expose a search action on a route (or use FOSJsRoutingBundle's path() in the widget).
  • Limit results (top 20 by LIKE %q%), return [{id: 1, text: '...'}].
  • Protect the endpoint — it is typically unauthenticated and leaks entity names.
  • Pair with a ModelTransformer (Doctrine's EntityType transformer works) so the ID string becomes an entity.

Pattern: collection with add/remove. Combine Symfony's native collection type with the bundle's JS (allow_add, allow_delete, prototype). The templates render the buttons; you supply the prototype and data-prototype. If the bundle JS fights yours, override the template and keep only the markup you need.

Pattern: Admingenerator integration. If you use symfony2admingenerator/generator-bundle, these types are exposed from generator YAML:

fields:
  roles:
    formType: double_list
  avatar:
    formType: image
    formOptions:
      upload_dir: uploads/avatars

That is the intended consumer — if that is your stack, friction is low. If not, you are using it out of context.

Pattern: standardise with a base type. Wrap recurring fields (rich text, image + preview, autocomplete) in your own type classes that hard-code sane defaults (required => false, size limits, CSS classes). When the bundle is eventually removed, you change three files instead of forty — and this also insulates you from alias/service-tag churn across Symfony upgrades.

Template overrides. Override individual widgets rather than whole themes:

# config/packages/twig.yaml
twig:
  form_themes:
    - 'Form/overrides.html.twig'   # extends the bundle's widget blocks

Or copy a block verbatim from Resources/views/Form/ and edit it. Cheapest way to fix Bootstrap 2 → 5 markup skew and to drop jQuery UI for your own datepicker.

Gotchas and Tips

  • String form type aliases no longer exist on modern Symfony. The bundle still defines and documents aliases like double_list, but Symfony 5+/6 resolves types by FQCN and by service tag. Write new code with FQCNs (Symfony2admingenerator\FormExtensionsBundle\Form\Type\DoubleListType::class); fall back to the alias only if you have explicitly registered it yourself. This is the single most common "it worked in the tutorial" failure.
  • The v4.1.2 change is in the DI extension base class. Nothing in your app needs to change unless you sub-classed the bundle's extension or copied its use statement into your own code — in which case swap the deprecated Extension import for the current one. Nothing else in the patch touches runtime behaviour.
  • Asset pipeline assumptions. The bundle expects jQuery + jQuery UI + Bootstrap loaded globally, historically via Assetic. Dropping it into a Webpack Encore / Vite project means every widget needs a template override and rewritten JS init. Budget for this; it can erase the entire time-saving benefit.
  • elFinder is a UI shell only. The type renders a file-picker button; you must run a separate elFinder PHP connector (route + filesystem roots + auth). Without it the popup opens empty with no error — the #1 "it's broken" report.
  • Upload directories are web-root-relative by default. Confirm resolution in the type before deploying: a trailing slash, a %kernel.project_dir% parameter, or a leading / can silently produce a path outside your writable tree. Assert is_writable() in a smoke test.
  • File name collisions and unsafe names. The types generally keep the client filename. Normalise it yourself (Slugger/uniqid) in your persistence listener, and validate the extension against an allow-list via File::guessExtension().
  • The delete checkbox clears the DB column, not the disk. Add an onFlush/postRemove handler, or compare against $em->getUnitOfWork()->getOriginalEntityData() in preUpdate.
  • AJAX endpoints and CSRF/session. The autocomplete issues GETs with the session cookie. If your firewall redirects unauthenticated requests to a login form, you get an HTML login page parsed as JSON and a silent "no results". Return 401 JSON explicitly for these routes.
  • Date/time formats use PHP date() tokens, not ICU/Intl patterns. 'format' => 'dd/MM/yyyy' will not do what you expect; the JS side may use a different format string than the PHP side. Mismatches show up as the picker silently rejecting valid input.
  • twig.form.resources order matters. An unstyled widget is almost always an earlier-registered theme claiming the block. Inspect with {{ dump(form.vars) }} and reorder form_themes (last wins for block inheritance, first wins for resource search — test empirically).
  • Config key quirks. Bundle options live under the extension key (form_extensions: by convention), often consumed by a Twig extension injecting <script>/<link> tags. If assets aren't injected, the extension isn't registered or the node name differs — read DependencyInjection/Configuration.php, not the README.
  • Extension points you actually have: (a) override templates, (b) extend the type class and re-register it under your own service id/tag, (c) override services via services.yaml, (d) a compiler pass to re-tag. There is no modern autoconfiguration.
  • Debugging checklist, in order: asset install → template resolution (twig.form_themes) → JS console for missing jQuery UI/plugins → type registered (debug:container grep for the FQCN or alias) → option names against configureOptions() → network tab for AJAX 302s.
  • Small, slow-moving project. v4.1.2 shows it is not abandoned — a community PR landed and was released — but PR frequency is low and there is no ecosystem pressure to keep it current with the newest Symfony. Assume you are, in practice, the maintainer of your integration: pin versions and keep a smoke test around the widgets you depend on.
  • Licence is listed as NOASSERTION. Read the LICENSE file before shipping commercially; do not assume MIT because the ecosystem usually is.
  • Long-term recommendation: for greenfield, prefer native Symfony types plus symfony/ux (Stimulus controllers for tom-select, file previews), VichUploaderBundle for uploads, FOSCKEditorBundle for rich text, and EasyAdmin/Sonata collection fields where they apply. Use this bundle when you are already on the Admingenerator stack and want the widgets for free; otherwise cherry-pick the type classes and templates you need into App\Form\Type / templates/form and drop the dependency.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin