Installation:
composer require b3da/dyn-form-bundle "dev-master"
Ensure your project uses Symfony 2.8 or 3.0.
Register Bundle:
Add to AppKernel.php:
new b3da\DynFormBundle\b3daDynFormBundle(),
Routing:
Include in routing.yml:
b3da_dyn_form:
resource: "@b3daDynFormBundle/Resources/config/routing.yml"
Configuration:
Enable translator and add Bootstrap form theme in config.yml:
translator: { fallbacks: ["%locale%"] }
twig:
form_themes: ['bootstrap_3_horizontal_layout.html.twig']
First Use Case:
Navigate to /forms/ to access the dynamic form demo. For custom forms, extend the bundle’s FormType classes (see src/b3da/DynFormBundle/Form/).
Define Dynamic Forms:
Extend b3da\DynFormBundle\Form\AbstractDynamicFormType to create reusable dynamic form types. Example:
namespace AppBundle\Form\Type;
use b3da\DynFormBundle\Form\AbstractDynamicFormType;
class UserProfileType extends AbstractDynamicFormType {
public function getName() { return 'user_profile'; }
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('name', TextType::class);
$builder->add('email', EmailType::class);
// Dynamically add fields based on logic
if ($options['is_admin']) {
$builder->add('admin_role', ChoiceType::class);
}
}
}
Integrate with Controllers: Use the form in controllers like standard Symfony forms:
public function editAction(Request $request, $id) {
$form = $this->createForm(UserProfileType::class, $user, ['is_admin' => true]);
// Handle submission...
}
Twig Integration:
Override form themes in templates/form/ to customize rendering. Example:
{% extends 'bootstrap_3_horizontal_layout.html.twig' %}
{% block form_row %}
<div class="form-group">
{{ form_label(form) }}
{{ form_widget(form) }}
{% if form.errors|length > 0 %}
<div class="help-block">{{ form_errors(form) }}</div>
{% endif %}
</div>
{% endblock %}
Dynamic Field Logic:
Use FormEvents (e.g., PRE_SET_DATA, PRE_SUBMIT) to modify forms dynamically:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$data = $event->getData();
if ($data->isPremium()) {
$event->getForm()->add('premium_field', TextType::class);
}
});
Validation: Leverage Symfony’s validation components. Example:
$builder->add('age', IntegerType::class, [
'constraints' => [new Assert\GreaterThan(18)]
]);
Bundle Maturity:
Twig Theme Conflicts:
bootstrap_3_horizontal_layout.html.twig exists in vendor/b3da/dyn-form-bundle/Resources/views/Form/ or override it in your project’s templates/form/ directory.php bin/console cache:clear) after theme changes.Dynamic Field Timing:
PRE_SUBMIT won’t trigger validation unless re-added in SUBMIT.PRE_SET_DATA for data-dependent fields (e.g., dropdown options based on user role).Database Schema:
Routing Overrides:
/forms/ route is for the demo. Avoid conflicts by extending the routing file:
# app/config/routing.yml
b3da_dyn_form_custom:
resource: "@AppBundle/Resources/config/routing.yml"
prefix: /custom
Form Dumping: Use Symfony’s form dumper to inspect dynamic forms:
$form->setData($user);
dump($form->createView());
Event Listener Debugging:
Add logging to FormEvents to trace dynamic modifications:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$this->logger->debug('Dynamic form data:', ['data' => $event->getData()]);
});
Cache Issues: Clear cache after:
Custom Form Types:
Extend AbstractDynamicFormType to create domain-specific dynamic forms. Example:
class SurveyType extends AbstractDynamicFormType {
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'questions' => [], // Array of question configs
]);
}
}
Override Templates:
Copy bootstrap_3_horizontal_layout.html.twig to templates/form/ and modify as needed. Example override for checkboxes:
{% block form_widget_simple %}
{% if form.vars.required and not form.vars.disabled %}
<span class="required">*</span>
{% endif %}
{{ form_widget(form) }} {{ form_label(form, null, {'label_attr': {'class': 'checkbox-inline'}}) }}
{% endblock %}
Add Validation Dynamically:
Use FormEvents::PRE_SUBMIT to add constraints based on runtime logic:
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
if ($data['is_active']) {
$event->getForm()->add('activation_date', DateType::class, [
'constraints' => [new Assert\NotBlank()],
]);
}
});
Integrate with API Platform:
For API-driven forms, combine with api-platform/core to expose dynamic forms as endpoints. Example:
# config/serializer/Entity.UserProfile.yaml
AppBundle\Entity\UserProfile:
attributes:
dynamic_fields: ~
How can I help you explore Laravel packages today?