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

Form Bundle Laravel Package

alsatian/form-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require alsatian/form-bundle
    

    Add to config/bundles.php (Symfony 4+):

    return [
        // ...
        Alsatian\FormBundle\AlsatianFormBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration (config/packages/alsatian_form.yaml):

    alsatian_form:
        extensible_choice: ~
        extensible_entity: ~
        extensible_document: ~
    
  3. First Use Case: Replace a standard ChoiceType with ExtensibleChoiceType in a form builder:

    use Alsatian\FormBundle\Form\ExtensibleChoiceType;
    
    $builder->add('tags', ExtensibleChoiceType::class, [
        'route' => 'ajax_tags',
        'attr_class' => 'select2-tags', // Optional: Override default class
    ]);
    

Key Files to Review

  • config/packages/alsatian_form.yaml (Configuration)
  • src/Form/ExtensibleChoiceType.php (Core type example)
  • templates/form/fields.html.twig (Optional: Override Twig templates)

Implementation Patterns

Common Workflows

1. Select2 AJAX Integration

  • Server-Side: Use route and route_params to define an AJAX endpoint:
    $builder->add('user', ExtensibleEntityType::class, [
        'class' => User::class,
        'choice_label' => 'email',
        'route' => 'app_user_autocomplete',
        'route_params' => ['role' => 'admin'],
    ]);
    
  • Client-Side: Initialize Select2 with AJAX config (example in README):
    $('.select2').select2({
        ajax: {
            url: $(this).data('ajax-url'), // Auto-populated by bundle
            dataType: 'json',
            delay: 250,
            data: function(params) {
                return { q: params.term, role: $(this).data('role') }; // Match route_params
            },
            processResults: function(data) {
                return { results: data.map(item => ({ id: item.id, text: item.email })) };
            }
        }
    });
    

2. Dynamic Forms with Extensible Types

  • Pattern: Use ExtensibleChoiceType for tags/categories where choices are added dynamically:
    $builder->add('categories', ExtensibleChoiceType::class, [
        'multiple' => true,
        'attr_class' => 'select2-categories',
        'route' => 'ajax_categories',
    ]);
    
  • Validation: Ensure submitted choices are validated in the controller:
    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $data = $form->getData();
        // $data['categories'] now includes both pre-defined and dynamically added choices
    }
    

3. Date/Time Pickers

  • Usage: Replace DateType/DateTimeType with DatepickerType/DateTimepickerType:
    $builder->add('birthday', DatepickerType::class);
    
  • Frontend Integration: Use libraries like Flatpickr or Pikaday with the pattern attribute auto-generated by the bundle.

4. Entity/Document Types

  • Entity Autocomplete:
    $builder->add('author', ExtensibleEntityType::class, [
        'class' => Author::class,
        'choice_label' => 'fullName',
        'route' => 'app_author_autocomplete',
    ]);
    
  • MongoDB Documents:
    $builder->add('document', ExtensibleDocumentType::class, [
        'class' => ProductDocument::class,
        'choice_label' => 'name',
        'route' => 'app_product_autocomplete',
    ]);
    

5. Autocomplete Text Fields

  • Basic Setup:
    $builder->add('search', AutocompleteType::class, [
        'route' => 'app_search_autocomplete',
        'attr_class' => 'autocomplete-search',
    ]);
    
  • Frontend: Use libraries like Awesomplete or Typeahead.js.

Integration Tips

1. Customizing HTML Attributes

  • Override default classes in config:
    alsatian_form:
        extensible_choice:
            attr_class: 'my-custom-select2'
    
  • Add custom data attributes per field:
    $builder->add('field', ExtensibleChoiceType::class, [
        'attr' => [
            'data-custom' => 'value',
            'data-role' => 'admin',
        ],
    ]);
    

2. Handling Submitted Data

  • Dynamically added choices are included in $form->getData(). Example:
    $form->submit($data);
    $submittedChoices = $data['extensible_field']; // Array of all choices (pre-defined + dynamic)
    

3. Twig Template Overrides

  • Override the default Twig template for a field:
    {# templates/form/fields.html.twig #}
    {% block alsatian_extensible_choice_widget %}
        <div class="custom-wrapper">
            {{ form_widget(form) }}
        </div>
    {% endblock %}
    

4. Symfony 6+ Flex Recipes

  • If using Symfony Flex, ensure the bundle is auto-discovered. For custom recipes, create a config/packages/alsatian_form.yaml manually.

5. Testing

  • Test AJAX routes separately:
    public function testAutocompleteRoute(): void
    {
        $client = static::createClient();
        $client->request('GET', '/ajax/tags?q=test');
        $this->assertJson($client->getResponse()->getContent());
    }
    
  • Test form submission with dynamic choices:
    $form->submit([
        'extensible_field' => ['existing_choice', 'new_dynamic_choice'],
    ]);
    $this->assertTrue($form->isValid());
    

Gotchas and Tips

Pitfalls

1. Missing AJAX Route Configuration

  • Issue: Select2 fails to load choices if the route option is missing or the route doesn’t exist.
  • Fix: Always define a route for AJAX endpoints:
    # config/routes.yaml
    ajax_tags:
        path: /ajax/tags
        controller: App\Controller\AjaxController::tagsAction
    
  • Debug: Check the rendered HTML for data-ajax--url. If empty, the route option is misconfigured.

2. Case Sensitivity in Choice Labels

  • Issue: choice_label must match the entity property exactly (including case). E.g., fullName vs. fullname.
  • Fix: Use property_path for complex labels:
    $builder->add('user', ExtensibleEntityType::class, [
        'class' => User::class,
        'choice_label' => 'property_path(user.fullName)',
    ]);
    

3. Doctrine MongoDB ODM Quirks

  • Issue: ExtensibleDocumentType may not work with nested documents or complex queries.
  • Fix: Ensure your repository method returns a simple array of [id, label] pairs:
    public function findByName($name)
    {
        return $this->createQueryBuilder()
            ->field('name')->equals(new \MongoDB\BSON\Regex($name))
            ->project(['id' => true, 'name' => true])
            ->getQuery()
            ->execute()
            ->toArray();
    }
    

4. CSRF Token Mismatch in AJAX

  • Issue: AJAX requests may fail with CSRF errors if the token isn’t included.
  • Fix: Include CSRF token in AJAX requests:
    $.ajaxSetup({
        headers: {
            'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
        }
    });
    

5. Symfony 5.4+ Deprecations

  • Issue: Some methods (e.g., setDefaultOptions) may trigger deprecation warnings.
  • Fix: Update to the latest version of the bundle or extend the types directly:
    use Alsatian\FormBundle\Form\ExtensibleChoiceType as BaseType;
    
    class CustomExtensibleChoiceType extends BaseType
    {
        public function configureOptions(OptionsResolver $resolver)
        {
            parent::configureOptions($resolver);
            $resolver->setDefaults([
                'attr' => ['data-custom' => 'value'],
            ]);
        }
    }
    

Debugging Tips

1. **Inspect

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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