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

Parsley Bundle Laravel Package

c0ntax/parsley-bundle

Symfony bundle that maps Symfony Form constraints and entity annotations to Parsley.js data-parsley-* attributes for client-side validation. Includes basic configuration (enable/trigger) and supports Email, Length, Pattern, Min/Max, Required, and Range.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle:

    composer require c0ntax/parsley-bundle
    

    Add to config/bundles.php (Symfony) or manually register in AppKernel.php if not using Flex.

  2. Enable Parsley.js: Include Parsley.js in your layout (e.g., base.html.twig):

    <script src="https://cdnjs.cloudflare.com/ajax/libs/parsley.js/2.9.2/parsley.min.js"></script>
    
  3. Basic Configuration (optional):

    # config/packages/c0ntax_parsley.yaml
    c0ntax_parsley:
        enabled: true
        field:
            trigger: "blur"  # Default: "focusout"
    
  4. First Use Case: Add a Symfony constraint to a form field (e.g., EmailType):

    // src/Form/YourFormType.php
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('email', EmailType::class, [
            'constraints' => [new Assert\Email()]
        ]);
    }
    

    The bundle auto-converts this to data-parsley-type="email" in the rendered HTML.


Implementation Patterns

1. Auto-Magic Symfony-to-Parsley Conversion

  • Workflow:
    1. Define Symfony constraints (e.g., Length, Email) in forms or entities.
    2. The bundle scans these during form rendering and injects data-parsley-* attributes.
    3. Parsley.js handles validation on the client side.
  • Example:
    // Entity with annotation
    /**
     * @Assert\Length(min=5, max=20)
     */
    private $username;
    
    Renders as:
    <input type="text" data-parsley-minlength="5" data-parsley-maxlength="20">
    

2. Client-Side Only Validations

  • Use the parsleys option for Parsley-specific rules not tied to Symfony:
    $builder->add('bio', TextType::class, [
        'parsleys' => [
            new \C0ntax\ParsleyBundle\Parsleys\Directive\Field\Constraint\MinLength(100, 'Bio must be at least 100 characters.')
        ]
    ]);
    

3. Overriding Auto-Generated Rules

  • Custom Error Messages: Override Symfony’s default error messages for Parsley:
    $builder->add('age', IntegerType::class, [
        'parsleys' => [
            new \C0ntax\ParsleyBundle\Parsleys\Directive\Field\ConstraintErrorMessage(
                \C0ntax\ParsleyBundle\Parsleys\Directive\Field\Constraint\Range::class,
                'Age must be between {{ min }} and {{ max }}.'
            )
        ]
    ]);
    
  • Removing Rules: Exclude specific constraints (e.g., Regex) from client-side validation:
    $builder->add('customField', TextType::class, [
        'constraints' => [new Assert\Regex('/pattern/')],
        'parsleys' => [new \C0ntax\ParsleyBundle\Parsleys\Directive\Field\RemoveSymfonyConstraint(Assert\Regex::class)]
    ]);
    

4. Field-Level Configuration

  • Override global trigger settings per field:
    $builder->add('username', TextType::class, [
        'parsley_trigger' => 'keyup'  // Overrides global `trigger` config
    ]);
    

5. Third-Party Entities

  • For Swagger-generated or external entities, use ConstraintErrorMessage to align error messages:
    $builder->add('externalField', TextType::class, [
        'parsleys' => [
            new \C0ntax\ParsleyBundle\Parsleys\Directive\Field\ConstraintErrorMessage(
                \C0ntax\ParsleyBundle\Parsleys\Directive\Field\Constraint\Email::class,
                'Please enter a valid email address.'
            )
        ]
    ]);
    

6. Extending with Custom Directives

  • Implement DirectiveInterface for custom Parsley attributes:
    use C0ntax\ParsleyBundle\Parsleys\Directive\DirectiveInterface;
    
    class CustomDirective implements DirectiveInterface {
        public function getAttributes(): array {
            return ['data-parsley-custom' => 'value'];
        }
    }
    
  • Register in a form:
    $builder->add('field', TextType::class, [
        'parsleys' => [new CustomDirective()]
    ]);
    

Gotchas and Tips

Pitfalls

  1. Unsupported Constraints:

    • Only a subset of Symfony constraints are supported (e.g., no Callback or Expression constraints).
    • Workaround: Use RemoveSymfonyConstraint for unsupported rules and add custom Parsley validations.
  2. Error Message Mismatches:

    • Parsley uses a single error message per validator, while Symfony may use dynamic messages (e.g., {{ limit }}).
    • Fix: Override with ConstraintErrorMessage (see Implementation Patterns).
  3. Parsley.js Not Loaded:

    • If Parsley.js is missing, validations silently fail.
    • Tip: Verify inclusion in your base template and check browser console for parsley.js errors.
  4. Trigger Conflicts:

    • Global trigger settings (e.g., focusout) may not suit all fields (e.g., keyup for search boxes).
    • Solution: Set parsley_trigger per field or adjust global config.
  5. Dynamic Forms:

    • The bundle processes forms at render time. Dynamic fields (e.g., added via JavaScript) require manual Parsley initialization.
    • Tip: Use Parsley.update() or reinitialize Parsley on dynamic content changes.
  6. Symfony 5+ Deprecations:

    • The bundle is outdated (last release: 2018). Test with Symfony 4.4+ and Parsley.js 2.x.
    • Tip: Fork the repo or patch for compatibility (e.g., Constraint class renames in Symfony 5).

Debugging Tips

  1. Inspect Rendered HTML: Check if data-parsley-* attributes are injected:

    <input data-parsley-required="true" data-parsley-trigger="focusout">
    
    • Missing attributes? Verify:
      • The constraint is supported (see Supported Validations).
      • The field is rendered in a Symfony form (not a custom template).
  2. Console Logs: Enable Parsley’s debug mode:

    window.Parsley.addValidator({
      name: 'debug',
      fn: function() { console.log('Parsley initialized'); return true; }
    });
    
  3. Disable Bundle Temporarily: Set enabled: false in config to isolate issues:

    c0ntax_parsley:
        enabled: false
    

Performance Quirks

  • Bundle Initialization: The bundle runs during form rendering, which may add slight overhead for complex forms. Tip: Disable for non-critical forms or use enabled: false in config.

  • Parsley.js Overhead: Parsley adds ~10KB to your bundle. For minimal forms, consider inlining Parsley or lazy-loading it.

Extension Points

  1. Custom Validators: Extend Parsley’s validators via JavaScript and map them to Symfony constraints using DirectiveInterface.

  2. Event Listeners: Hook into form events (e.g., PRE_SET_DATA) to dynamically modify Parsley rules:

    // src/EventListener/ParsleyListener.php
    public function onPreSetData(FormEvent $event) {
        $form = $event->getForm();
        if ($form->getName() === 'dynamic_form') {
            $form->add('field', TextType::class, [
                'parsleys' => [new CustomDirective()]
            ]);
        }
    }
    
  3. Twig Integration: Access Parsley attributes in Twig for custom templates:

    {{ form_widget(form.field, {
        'attr': {
            'data-parsley-custom': '{{ form.vars.data.parsley_custom }}'
        }
    }) }}
    

Configuration Deep Dive

  • Global vs. Field-Level Triggers:

    • Global: c0ntax_parsley.field.trigger (e.g., focusout).
    • Field-level: Override with 'parsley_trigger' => 'keyup' in form options.
  • Disabling for Specific Fields: Use RemoveParsleyDirective to exclude Parsley from

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