clickandmortar/oro-platform-advanced-form-bundle
Installation:
composer require clickandmortar/oro-platform-advanced-form-bundle
php bin/console cache:clear
Verify compatibility with your OroPlatform version (e.g., 4.2.* for OroPlatform 4.2.*).
First Use Case:
Create a custom form type by extending CmAdvancedFormBundle\Form\Type\AbstractAdvancedFormType and register it in your bundle’s Resources/config/services.yml:
services:
app.form.type.my_custom_form:
class: App\Form\Type\MyCustomFormType
tags:
- { name: form.type, alias: my_custom_form }
Key Files to Review:
src/Form/Type/AbstractAdvancedFormType.php (base class for custom form types).src/DependencyInjection/Configuration.php (bundle configuration).docs/demo.gif (visual reference for expected behavior).Extending Form Types:
Override buildForm() and configureOptions() in your custom form type to add fields, validation, or logic:
namespace App\Form\Type;
use CmAdvancedFormBundle\Form\Type\AbstractAdvancedFormType;
class MyCustomFormType extends AbstractAdvancedFormType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('field1', TextType::class)
->add('field2', ChoiceType::class, [
'choices' => ['Option 1', 'Option 2'],
]);
}
}
Dynamic Field Loading:
Use AbstractAdvancedFormType’s loadFieldDefinitions() to dynamically add fields based on runtime logic (e.g., entity metadata):
protected function loadFieldDefinitions(FieldDefinitionCollection $collection) {
$collection->add('dynamic_field', new FieldDefinition('text', TextType::class));
}
Integration with OroCRM Entities:
Attach forms to entity types via YAML (e.g., config/oro_entity_extend.yml):
oro_entity:
entity_definitions:
my_entity:
form_types:
default: app.form.type.my_custom_form
Submitting and Handling Forms: Use Symfony’s form handling workflow with Oro’s entity managers:
$form = $this->createForm(MyCustomFormType::class, $entity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($entity);
$em->flush();
}
Theming:
Override Twig templates in templates/form/ or extend the base template (@CmAdvancedForm/form.html.twig).
Version Mismatch:
3.1.* and 4.2.*. Mixing versions (e.g., OroCRM 4.1.* with this bundle) may break dependencies.composer.json:
"require": {
"oro/platform": "4.2.*"
}
Caching Issues:
php bin/console cache:clear --env=prod --no-debug
--env=dev during development to avoid cache-related headaches.Form Type Registration:
form.type will make the form type invisible to Symfony’s form factory.services.yml includes:
tags:
- { name: form.type, alias: your_form_alias }
Entity Form Overrides:
oro_entity.form.build) for safer extensions:
// src/EventListener/FormListener.php
public function onBuildForm(FormEvent $event) {
$form = $event->getForm();
$form->add('custom_field', TextType::class);
}
Register the listener in services.yml:
tags:
- { name: kernel.event_listener, event: oro_entity.form.build, method: onBuildForm }
Dynamic Fields and Hydration:
loadFieldDefinitions() won’t auto-hydrate from entity data unless you implement setDefaultOptions():
public function setDefaultOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => MyEntity::class,
'csrf_protection' => true,
]);
}
Debugging Form Data: Dump form data in a controller to verify field binding:
$data = $form->getData();
dump($data); // Check if dynamic fields are populated.
Reusing Field Definitions:
Create a base form type for shared fields (e.g., BaseEntityFormType) and extend it for specific entities to avoid duplication.
Performance:
loadFieldDefinitions() if the form has many dynamic fields:
protected function loadFieldDefinitions(FieldDefinitionCollection $collection) {
if ($this->shouldLoadFields()) {
$collection->add('heavy_field', new FieldDefinition('text', TextType::class));
}
}
Testing:
Use Oro’s EntityTestCase to test form submissions:
public function testFormSubmission() {
$formData = ['field1' => 'value'];
$form = $this->factory->create(MyCustomFormType::class, null, ['csrf_protection' => false]);
$form->submit($formData);
$this->assertTrue($form->isValid());
}
Extending the Bundle:
vendor/clickandmortar/oro-platform-advanced-form-bundle/Resources/views/ to templates/CmAdvancedForm/.AbstractAdvancedFormType to add global form behaviors (e.g., auto-save logic).OroCRM-Specific:
entity_alias in form options to avoid hydration issues:
$builder->add('entity_field', EntityType::class, [
'class' => 'OroCRM:Account',
'property' => 'entity_alias',
]);
```markdown
## Extension Points
1. **Custom Field Types**:
Extend `CmAdvancedFormBundle\Form\Type\Field\AbstractFieldType` to create reusable field components.
2. **Form Events**:
Listen to `cm_advanced_form.build` and `cm_advanced_form.submit` events for cross-cutting concerns:
```yaml
tags:
- { name: kernel.event_listener, event: cm_advanced_form.build, method: onFormBuild }
Data Transformers:
Implement DataTransformerInterface for custom field data mapping (e.g., converting arrays to JSON).
Validation Groups:
Dynamically set validation groups in configureOptions():
$resolver->setDefaults([
'validation_groups' => function (FormInterface $form) {
return ['Default', 'custom_group'];
},
]);
Asset Integration:
Load JavaScript/CSS for dynamic forms via buildView():
public function buildView(FormView $view, FormInterface $form, array $options) {
$view->vars['cm_advanced_form_assets'] = $this->assetHelper->getAssets();
}
How can I help you explore Laravel packages today?