Collection Form Type
softspring/collection-form-type is a browser-side helper for dynamic collection forms.
It does not provide a Symfony PHP form type. Its value is the JavaScript layer that turns collection markup into an interactive UI with actions such as add, insert, move, duplicate, copy, paste, and delete.
This is especially useful in complex admin forms where collection entries behave more like editable blocks than simple repeated inputs.
Installation
Install the Composer package:
composer require softspring/collection-form-type:^6.0
Then import the JavaScript in your asset build:
import '@softspring/collection-form-type/scripts/collection-form-type';
This is how cms-bundle and armonic integrate it.
When To Use It
Use this package when your form collection needs interactive behavior such as:
- add a new node at the end
- insert a node at a specific position
- move nodes up or down
- duplicate an existing node
- copy and paste nodes through the clipboard
- keep indexes and names synchronized after reordering
If you only need a plain Symfony CollectionType with simple add and remove buttons, this package is usually more than you need.
DOM Contract
The package works through data attributes.
The core markers are:
data-collection="collection"on the collection containerdata-collection="node"on each collection itemdata-collection-actionon action buttons
The collection or the action element must also expose the prototype information through attributes such as:
data-prototypedata-prototype-namedata-collection-prototypedata-collection-prototype-name
The script reads those values and uses them to generate or insert new nodes.
Supported Actions
The package listens to click actions with these values:
addinsertdeleteupdownduplicatecopypaste
Example:
<button type="button" data-collection-action="add" data-collection-target="menu_items">
Add item
</button>
What Each Action Does
Add
Adds a new node at the end of the collection.
Use it for the standard “append new item” flow.
Insert
Inserts a new node before a specific position.
This is useful when the UI needs insertion bars or “add here” controls between nodes.
Delete
Removes the current node and then reindexes the following nodes.
Up And Down
Moves the current node in the collection and updates indexes, ids, and full names so the form stays consistent.
Duplicate
Clones the current node in place and then reindexes the following nodes.
This is useful for content blocks or repeated items that often start from an existing node.
Copy And Paste
The package can serialize a node to clipboard-friendly JSON, then paste it back into the collection.
This is especially useful in CMS-like UIs where editors reuse a block structure instead of recreating it by hand.
Lifecycle Events
The component is event-driven.
For each main action, it dispatches before and after events such as:
collection.node.add.beforecollection.node.add.aftercollection.node.insert.beforecollection.node.insert.aftercollection.node.delete.beforecollection.node.delete.aftercollection.node.duplicate.beforecollection.node.duplicate.after
This is one of the main reasons to use the package: application code can hook into the lifecycle without forking the library.
Event Context
The custom events expose helper methods to work with:
- collection
- node
- position
- prototype name
- prototype
- original browser event
That makes it possible to customize the default behavior during before events, for example:
- change the collection target
- change the insertion position
- replace the prototype HTML
- validate or reject clipboard data
Copy And Paste Validation
Copy and paste support uses a dedicated validation event:
collection.node.copy.preparecollection.node.paste.validate
This gives the application a place to inspect or modify clipboard payloads before the paste happens.
That is useful when:
- only some collection payloads should be accepted
- the application wants to add metadata
- clipboard content should be transformed before insertion
Index And Name Synchronization
One of the important jobs of the package is keeping collection nodes consistent after structural changes.
When nodes move or duplicate, the script updates:
data-collection-index- node ids
data-full-name- matching references inside the node HTML
Without that step, Symfony collection submissions would quickly become inconsistent after reordering or duplication.
Typical Integration Pattern
The most common pattern is:
- render a collection with
data-collection="collection" - render each item with
data-collection="node" - render action buttons with
data-collection-action - import the package JS in the admin asset build
- listen to the lifecycle events when the project needs custom behavior
This is the approach used by cms-bundle for menus, routes, and content modules.
Extension Patterns
Good extension patterns are:
- listening to
beforeevents to change prototype or destination - listening to
afterevents to update UI state - validating paste payloads before insertion
- adding project-specific behavior on top of the generic collection events
This lets the package stay generic while the application owns the domain-specific behavior.
Current Limits
- The package depends on browser clipboard support for copy and paste features.
- It relies on correct HTML data attributes and correctly generated prototypes.
- It initializes from browser load events, so the script should be loaded as part of the normal page asset build.
- It is a JavaScript collection helper, not a Symfony PHP form type by itself.