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

Twigx Bundle Laravel Package

almacareer/twigx-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require almacareer/twigx-bundle
    

    For Symfony Flex projects, the bundle auto-registers. Otherwise, add to bundles.php:

    AlmaCareer\TwigXBundle\TwigXBundle::class => ['all' => true],
    
  2. First Use Case: Create a Twig component template (e.g., templates/components/Button.twig) and use JSX-like syntax in your template:

    <Button type="primary" onClick={handleClick}>Click Me</Button>
    

    The bundle maps this to:

    {% embed "@spirit/Button.twig" with { props: { type: 'primary', onClick: handleClick } } %}
        Click Me
    {% endembed %}
    
  3. Default Paths: Components are resolved from %kernel.project_dir%/templates/components by default. Override via config/packages/twigx.yml:

    twigx:
        paths:
            - "%kernel.project_dir%/templates/custom-components"
        paths_alias: 'custom-ui'
    

Implementation Patterns

1. Component Usage

  • JSX-like Syntax:

    <Alert type="success" message={user.message} />
    <Link href="/dashboard" class="btn">Go to Dashboard</Link>
    

    Supports:

    • Attributes: type="primary", href="/path", class="btn".
    • Dynamic Props: {variable}, {{ ternary ? 'yes' : 'no' }}.
    • Boolean Props: isOpen, isDisabled={false}.
    • Self-Closing: <ButtonLink />.
  • Fallback to Twig:

    {% embed "@custom-ui/Button.twig" with { props: { text: 'Click' } } %}
        {{ props.text }}
    {% endembed %}
    

2. Component Organization

  • Directory Structure:
    templates/
    ├── components/
    │   ├── Button.twig
    │   ├── Alert.twig
    │   └── ...
    └── pages/
        └── home.twig
    
    Use paths in twigx.yml to include multiple directories:
    twigx:
        paths:
            - "%kernel.project_dir%/templates/components"
            - "%kernel.project_dir%/templates/vendor-components"
    

3. Dynamic Props Handling

  • JSX Syntax:

    <TextField
        label="Username"
        value={user.username}
        onChange={handleChange}
    />
    

    Maps to Twig props:

    {% set props = {
        label: 'Username',
        value: user.username,
        onChange: handleChange
    } %}
    
  • Twig Syntax (Mixed):

    <Component attr={{ dynamicValue }} other={staticValue} />
    

4. Integration with Symfony Forms

  • Form Component Example:
    <FormField
        label="Email"
        type="email"
        value={form.email.value}
        errors={form.email.errors}
        onChange={form.email.onChange}
    />
    
    Render the form field as a Twig component with props for validation errors.

5. Conditional Rendering

  • Ternary Conditions:
    <Button
        type={isAdmin ? 'admin' : 'user'}
        disabled={!isActive}
    >
        {isAdmin ? 'Admin Panel' : 'User Dashboard'}
    </Button>
    

6. Extending Components

  • Override Defaults: Create a custom component (e.g., CustomButton.twig) and reference it via paths_alias:
    twigx:
        paths:
            - "%kernel.project_dir%/templates/custom-components"
        paths_alias: 'custom'
    
    Use in templates:
    <custom:CustomButton size="large">Submit</custom:CustomButton>
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity:

    • Component tags must start with a capital letter (e.g., <Button> not <button>).
    • Template filenames should match the component name (e.g., Button.twig for <Button>).
  2. Attribute Parsing:

    • Hyphenated Props: Only work if written as kebab-case (e.g., data-test="value"). ❌ Fails: dataTest="value".
    • Whitespace in Props: Avoid spaces inside {} or {{}} (e.g., { value } works, but {{ value }} may fail).
  3. Boolean Props:

    • Use is* prefix for booleans (e.g., isDisabled={true}).
    • Omitting the value sets it to true (e.g., <Button isOpen>).
  4. Twig Comments:

    • Comments inside props (e.g., {/* comment */ value}) are stripped during parsing.
    • Place comments outside props or use Twig’s native {% comment %}.
  5. Self-Closing Tags:

    • Ensure /> is used for void components (e.g., <ButtonLink />).
    • Avoid trailing content (e.g., <ButtonLink />Text will fail).
  6. Configuration Overrides:

    • If paths_alias is not set, the default alias (spirit) is used.
    • Glob Patterns: Use * for wildcards (e.g., templates/components/*/Button.twig).

Debugging Tips

  1. Check Parsed Props: Enable Twig debug mode (APP_DEBUG=true) to inspect how props are rendered in the final HTML.

  2. Component Not Found:

    • Verify the template file exists at the configured paths.
    • Ensure the filename matches the component name (case-sensitive).
  3. Syntax Errors:

    • Use the official JSX guide as a reference for valid syntax.
    • Validate props in {{ }} or {} separately (e.g., test {{ variable }} in a plain Twig template first).
  4. Caching Issues: Clear Symfony cache after adding new components:

    php bin/console cache:clear
    

Extension Points

  1. Custom Lexer/Parser: Extend the bundle’s TwigXLexer or TwigXParser to support additional syntax (e.g., custom attributes).

  2. Component Inheritance: Use Twig’s {% extends %} in component templates to share logic:

    {# templates/components/BaseButton.twig #}
    <button class="base-button {{ props.class }}">
        {% block content %}{% endblock %}
    </button>
    
    {# templates/components/PrimaryButton.twig #}
    {% extends "@custom-ui/BaseButton.twig" %}
    {% block content %}{{ props.children }}{% endblock %}
    
  3. Dynamic Component Loading: Load components dynamically via twigx.yml paths or use Symfony’s ContainerAware interfaces to fetch paths at runtime.

  4. Integration with Stimulus: Pass Stimulus controllers as props:

<Modal isOpen={isModalOpen} controller="modal" controllerParams={{ { target: 'modal' } }}

  Content

Performance Considerations

  1. Component Caching: The bundle leverages Twig’s built-in caching. Ensure your twig.cache_warmer is configured for optimal performance.

  2. Avoid Over-Embedding: Limit nested components to reduce template complexity and improve render times.

  3. Static Props: Prefer static props (e.g., type="primary") over dynamic ones (e.g., {type}) where possible to minimize runtime processing.


Advanced Patterns

  1. Slot Content: Use Twig’s {{ content() }} in component templates to support slot-like content:

    {# templates/components/Card.twig #}
    <div class="card">
        <div class="card-header">{{ props.header }}</div>
        <div class="card-body">{{ content() }}</div>
    </div>
    

    Usage:

    <Card header="Title">
        <p>Card content</p>
    </Card>
    
  2. Component Events: Dispatch custom events via props (e.g., onCustomEvent={handleEvent}) and handle them in JavaScript:

    <Component onCustomEvent={dispatchEvent} />
    
    document.querySelector('[data-component]').addEventListener('customEvent', (e) => {
        console.log(e.detail);
    });
    
  3. TypeScript Support: Generate .d.ts files for IDE autocompletion by parsing your component templates (requires custom tooling). Example:

    interface ButtonProps {
        type
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle