Weave Code
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

Dependent Forms Bundle Laravel Package

anacona16/dependent-forms-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle
    composer require anacona16/dependent-forms-bundle
    
  2. Enable the Bundle Add to config/bundles.php:
    Anacona16\Bundle\DependentFormsBundle\DependentFormsBundle::class => ['all' => true],
    
  3. Import Routes Add to config/routes/dependent_forms.yaml:
    anacona16_dependent_forms:
        resource: '@DependentFormsBundle/Resources/config/routing.xml'
    
  4. Configure Twig Update config/packages/twig.yaml:
    twig:
        form_themes:
            - '@DependentForms/Form/fields.html.twig'
    
  5. Install Assets
    php bin/console assets:install --symlink
    
  6. Load jQuery Include in your base template:
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    

First Use Case: Basic Dependent Form

Create a form with dependent fields (e.g., country → state/city):

use Anacona16\Bundle\DependentFormsBundle\Form\Type\DependentType;

$builder->add('country', EntityType::class, [
    'class' => Country::class,
    'choices' => $countries,
]);

$builder->add('state', DependentType::class, [
    'dependent_field' => 'country',
    'dependent_field_options' => [
        'class' => State::class,
        'query_builder' => function (EntityRepository $er, $countryId) {
            return $er->createQueryBuilder('s')
                ->where('s.country = :country')
                ->setParameter('country', $countryId);
        },
    ],
]);

Implementation Patterns

Common Workflows

  1. Dynamic Field Population Use DependentType for fields that depend on another field's value (e.g., dropdowns, selects).

    $builder->add('city', DependentType::class, [
        'dependent_field' => 'state',
        'dependent_field_options' => [
            'class' => City::class,
            'query_builder' => function (EntityRepository $er, $stateId) {
                return $er->createQueryBuilder('c')
                    ->where('c.state = :state')
                    ->setParameter('state', $stateId);
            },
        ],
    ]);
    
  2. Custom Query Logic Override query_builder to fetch data dynamically:

    'query_builder' => function (EntityRepository $er, $parentValue) {
        return $er->createQueryBuilder('e')
            ->where('e.parent = :parent')
            ->andWhere('e.is_active = :active')
            ->setParameter('parent', $parentValue)
            ->setParameter('active', true);
    },
    
  3. Non-Entity Dependencies Use choices instead of class for non-DOCTRINE entities:

    'dependent_field_options' => [
        'choices' => $this->getDynamicChoices($parentValue),
    ],
    
  4. Chaining Dependencies Nested dependencies (e.g., country → state → city):

    $builder->add('country', EntityType::class, [...]);
    $builder->add('state', DependentType::class, [
        'dependent_field' => 'country',
        // ...
    ]);
    $builder->add('city', DependentType::class, [
        'dependent_field' => 'state',
        // ...
    ]);
    
  5. Form Events for Pre-Fetching Use PRE_SET_DATA to pre-load dependent fields:

    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();
    
        if ($data && $data->getCountry()) {
            $form->get('state')->setData($data->getState());
        }
    });
    

Gotchas and Tips

Pitfalls

  1. jQuery Dependency

    • The bundle requires jQuery for client-side behavior. Forgetting to include it will break dependent field updates.
    • Fix: Always include jQuery before the bundle's JS assets.
  2. Circular Dependencies

    • Avoid circular dependencies (e.g., A depends on B, B depends on A). The bundle does not handle this natively.
    • Fix: Use form events or custom logic to manage such cases.
  3. Query Builder Pitfalls

    • If query_builder returns no results, the dependent field will not update.
    • Fix: Ensure your query_builder always returns a valid QueryBuilder, even if empty:
      return $er->createQueryBuilder('e')
          ->where('1=1') // Fallback to all records if no filter
          ->setParameter('parent', $parentValue);
      
  4. Symfony 5+ Compatibility

    • The bundle is tested for Symfony 5.0+, but some older patterns (e.g., FormTypeExtension) may need adjustments.
    • Fix: Check the documentation for Symfony 5-specific notes.
  5. Caching Issues

    • If dependent fields don’t update, clear the cache:
      php bin/console cache:clear
      
  6. CSRF Token Conflicts

    • If using AJAX to submit dependent forms, ensure CSRF tokens are included:
      $.ajaxSetup({
          headers: {
              'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
          }
      });
      

Debugging Tips

  1. Check Network Requests

    • Open browser dev tools (F12) and verify AJAX requests are firing when changing the parent field.
  2. Log Query Builders

    • Debug query_builder logic by logging the generated SQL:
      $queryBuilder = $er->createQueryBuilder('e')
          ->where('e.parent = :parent')
          ->setParameter('parent', $parentValue);
      \Log::debug($queryBuilder->getQuery()->getSQL());
      
  3. Disable JavaScript Temporarily

    • If dependent fields work in the form but not in the UI, the issue is likely JavaScript-related.
  4. Verify Twig Theme

    • Ensure @DependentForms/Form/fields.html.twig is loaded. Override it if needed:
      twig:
          form_themes:
              - 'bundles/yourbundle/form/fields.html.twig'
      

Extension Points

  1. Custom Templates Override the Twig template to modify rendering:

    {% extends '@DependentForms/Form/fields.html.twig' %}
    {% block dependent_field_widget %}
        {{ parent() }} <!-- Customize here -->
    {% endblock %}
    
  2. Event Listeners Extend functionality with form events:

    $builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();
        // Custom logic
    });
    
  3. Ajax Customization Override the bundle’s JavaScript behavior by extending its assets:

    // public/js/dependent-forms.js
    $(document).on('change', '.dependent-field', function() {
        // Custom AJAX logic
    });
    

    Then include it after jQuery:

    <script src="{{ asset('js/dependent-forms.js') }}"></script>
    
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.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views