agence-adeliom/easy-editor-bundle
Flexible content editor for EasyAdmin: store content as JSON blocks, build custom block types, render via Twig with an included form theme, and hook into events during block rendering. Symfony Flex install; supports Symfony 6.4/7.x (v3) and older branches.
Install the Bundle
composer require agence-adeliom/easy-editor-bundle
Ensure your composer.json includes the GitHub recipes endpoint for Symfony Flex.
Configure EasyAdmin
Add the bundle to your config/bundles.php:
return [
// ...
AgenceAdeliom\EasyEditorBundle\AgenceAdeliomEasyEditorBundle::class => ['all' => true],
];
Define an Entity with Content Field
Use the EasyEditorType in your entity:
use AgenceAdeliom\EasyEditorBundle\Type\EasyEditorType;
#[ORM\Entity]
class Article
{
#[ORM\Column(type: 'text', nullable: true)]
#[EasyEditor]
private ?string $content = null;
}
Register the Field in EasyAdmin
use AgenceAdeliom\EasyEditorBundle\Field\EasyEditorField;
$crud->addField(EasyEditorField::new('content'));
Render Content in Twig
Use the easy_editor_render Twig function:
{{ easy_editor_render(article.content) }}
Create a blog post entity with a rich-text content field. Use EasyEditorField in EasyAdmin to let users edit the content with the bundled editor (e.g., TinyMCE or CKEditor, depending on configuration). Render the output in Twig templates using easy_editor_render.
Define Custom Blocks
Extend the BlockInterface to create reusable components (e.g., ImageBlock, QuoteBlock):
use AgenceAdeliom\EasyEditorBundle\Block\BlockInterface;
class ImageBlock implements BlockInterface
{
public function getType(): string { return 'image'; }
public function render(array $data): string { /* ... */ }
}
Register Blocks in Configuration
# config/packages/easy_editor.yaml
agence_adeliom_easy_editor:
blocks:
image: App\Block\ImageBlock
quote: App\Block\QuoteBlock
Use Blocks in Editor The editor UI will now include buttons/toolbars for your custom blocks. Users can insert them into the content.
Field Customization Configure the editor toolbar, height, or plugins:
$crud->addField(
EasyEditorField::new('content')
->setToolbar(['bold', 'italic', 'image', 'quote'])
->setHeight(400)
);
Validation
Add validation rules to the content field in your entity:
#[Assert\NotBlank(groups: ['easy_editor'])]
#[Assert\Length(max: 10000, groups: ['easy_editor'])]
private ?string $content;
Event Listeners
Listen to easy_editor.pre_render or easy_editor.post_render events to modify content dynamically:
use AgenceAdeliom\EasyEditorBundle\Event\EasyEditorEvent;
$eventDispatcher->addListener(EasyEditorEvent::PRE_RENDER, function (EasyEditorEvent $event) {
$event->setContent(str_replace('foo', 'bar', $event->getContent()));
});
Render Raw or Processed Content
{{ article.content|raw }}
{{ easy_editor_render(article.content) }}
Pass Additional Context Override the Twig function in your bundle to pass extra variables:
{{ easy_editor_render(article.content, {'custom_var': true}) }}
Block Registration Order
Blocks registered later may override earlier ones. Use unique names (e.g., app.image_block) to avoid conflicts.
Twig Auto-escaping
easy_editor_render escapes output by default. Use |raw if you trust the content:
{{ easy_editor_render(article.content)|raw }}
Editor Plugin Dependencies Some editors (e.g., TinyMCE) require additional JS/CSS assets. Ensure they are loaded in your base template:
{{ easy_editor_assets() }}
Database Storage
The bundle stores content as plain text. For large content, consider compressing it or using a dedicated field type (e.g., json).
Check Block Rendering Enable debug mode to see unregistered block types in logs:
agence_adeliom_easy_editor:
debug: true
Editor Configuration Override the default editor config via YAML:
agence_adeliom_easy_editor:
editor:
tiny_mce:
plugins: ['image', 'code', 'custom_block']
Event Debugging Dump event data in listeners:
$eventDispatcher->addListener(EasyEditorEvent::PRE_RENDER, function (EasyEditorEvent $event) {
\Symfony\Component\Debug\Debug::dump($event->getContent());
});
Custom Editor Integration Replace the default editor (e.g., switch from TinyMCE to CKEditor) by extending the bundle or using a separate asset pipeline.
Block Serialization Override the serializer for custom block data formats:
use AgenceAdeliom\EasyEditorBundle\Serializer\BlockSerializerInterface;
$container->set(BlockSerializerInterface::class, CustomBlockSerializer::class);
Asset Management
Extend the EasyEditorAssets service to include additional JS/CSS:
use AgenceAdeliom\EasyEditorBundle\DependencyInjection\EasyEditorExtension;
public function load(array $configs, ContainerConfigurator $container): void
{
$container->parameters()->set('agence_adeliom_easy_editor.assets', [
'js' => ['/path/to/custom.js'],
]);
}
Lazy-Load Blocks Defer block registration until needed to reduce memory usage:
$blockRegistry->add('dynamic_block', DynamicBlock::class, true);
Cache Rendered Content
Cache the output of easy_editor_render in your templates:
{% cache app_easy_editor_article_{{ article.id }} %}
{{ easy_editor_render(article.content) }}
{% endcache %}
How can I help you explore Laravel packages today?