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

Knp Components Laravel Package

knplabs/knp-components

Knp Components is a PHP component library from KnpLabs. It currently includes the Pager component for building flexible, “fancy” pagination and paging adapters. PHPUnit 10/11 supported; install with Composer and run the test suite via composer test.

View on GitHub
Deep Wiki
Context7
## Getting Started

### **First Steps**
1. **Installation**
   ```bash
   composer require knplabs/knp-components:^5.2.0

Register the service provider in config/app.php under providers:

KnpLabs\KnpComponents\ComponentProvider::class,
  1. Basic Usage The package provides a component-based architecture for reusable UI elements (e.g., paginators, modals, alerts). Start by exploring the built-in components:

    • Paginator: The most commonly used component (now optimized for accurate item counts with PR #348).
    • Modal: For dialogs and overlays.
    • Alert: For notifications (success, error, etc.).
  2. First Use Case: Paginator

    use KnpLabs\KnpComponents\Component\Paginator\PaginatorComponent;
    
    // In a controller or service
    $paginator = new PaginatorComponent(
        $items, // Your collection/array
        $currentPage,
        $perPage,
        $totalItems
    );
    
    // Pass to Blade
    return view('your.view', ['paginator' => $paginator]);
    

    In Blade:

    {!! $paginator->render() !!}
    

    Note: v5.2.0 removes the ORDER BY clause from item count queries (PR #348), improving performance for large datasets.


Implementation Patterns

1. Component Composition

  • Reusable Components: Extend or override built-in components (e.g., PaginatorComponent) to fit your design system.

    class CustomPaginator extends PaginatorComponent
    {
        public function render(): string
        {
            // Customize rendering logic
            return '<div class="custom-paginator">' . parent::render() . '</div>';
        }
    }
    
  • Dependency Injection: Components accept dependencies (e.g., ViewRenderer, UrlGenerator) via constructor. Use Laravel’s DI container for flexibility. New: The knp_pager.items event now passes an ArgumentAccess object (PR #343), enabling granular access to paginator arguments for event listeners.

2. Blade Integration

  • Dynamic Rendering: Components can be rendered conditionally:

    @if($hasItems)
        {!! $paginator->render() !!}
    @endif
    
  • Slot-Based Layouts: Use Blade slots for customizable sections (e.g., modal headers/footers):

    {!! $modal->render([
        'header' => '<h3>Custom Header</h3>',
        'footer' => '<button>Close</button>',
    ]) !!}
    

3. API-Driven Workflows

  • Server-Side Pagination: Fetch paginated data via API (e.g., Laravel’s paginate()) and pass it to the component:

    $items = YourModel::paginate(10);
    $paginator = new PaginatorComponent($items->items(), $items->currentPage(), $items->perPage(), $items->total());
    

    Optimization: v5.2.0 ensures accurate item counts without unnecessary ORDER BY clauses (PR #348).

  • AJAX Updates: Use JavaScript to update paginators dynamically (e.g., infinite scroll):

    document.querySelector('.paginator-next').addEventListener('click', (e) => {
        fetch(`/api/items?page=${nextPage}`)
            .then(response => response.json())
            .then(data => {
                // Update DOM with new paginator component
            });
    });
    

4. Event-Driven Extensibility

  • Listen to Paginator Events: Leverage the knp_pager.items event with the new ArgumentAccess object:

    use KnpLabs\KnpComponents\Component\Paginator\Event\PaginatorItemsEvent;
    use Symfony\Component\OptionsResolver\ArgumentAccess;
    
    Event::listen(PaginatorItemsEvent::class, function (PaginatorItemsEvent $event) {
        $access = $event->getArgumentAccess();
        $currentPage = $access->get('currentPage');
        // Custom logic based on paginator arguments
    });
    
  • Testing Components: Mock dependencies (e.g., ViewRenderer) to test component logic:

    $viewRenderer = Mockery::mock(ViewRenderer::class);
    $paginator = new PaginatorComponent([], 1, 10, 100, $viewRenderer);
    $this->assertStringContainsString('page 1', $paginator->render());
    

Gotchas and Tips

Pitfalls

  1. Blade vs. Plain PHP Rendering

    • Components render HTML by default. For non-Blade contexts (e.g., APIs), use renderAsString() or renderToResponse():
      $html = $paginator->renderAsString();
      
  2. URL Generation in Components

    • Components use Laravel’s UrlGenerator. If URLs are incorrect, verify:
      • The APP_URL in .env.
      • The UrlGenerator is bound correctly in the DI container.
  3. Component State Management

    • Components are stateless by design. For dynamic behavior (e.g., modals), use JavaScript or Laravel’s session:
      // In a controller
      session(['modal_open' => true]);
      
      @if(session('modal_open'))
          {!! $modal->render() !!}
      @endif
      
  4. Item Count Accuracy (v5.2.0)

    • Fix: PR #348 removes ORDER BY clauses from item count queries, preventing performance issues with large datasets. Ensure your queries return correct totals without implicit ordering.

Debugging Tips

  1. Inspect Rendered HTML Use dd($paginator->render()) to debug output before passing to Blade.

  2. Override Default Templates Components use Blade templates under resources/views/vendor/knp-components/. Override them by copying to your project:

    cp vendor/knplabs/knp-components/resources/views/vendor/knp-components/* resources/views/vendor/knp-components/
    
  3. Custom CSS/JS Components include minimal styling. Extend with your own assets:

    <link rel="stylesheet" href="{{ asset('css/paginator.css') }}">
    {!! $paginator->render() !!}
    
  4. Event Debugging

    • Use ArgumentAccess in event listeners to inspect paginator arguments:
      $event->getArgumentAccess()->get('totalItems');
      

Extension Points

  1. Create Custom Components Extend AbstractComponent to build domain-specific components:

    class UserCardComponent extends AbstractComponent
    {
        public function __construct(private User $user) {}
    
        public function render(): string
        {
            return view('components.user-card', ['user' => $this->user])->render();
        }
    }
    
  2. Hook into Component Events Use events (e.g., PaginatorComponent::PAGE_CHANGED) or the new knp_pager.items with ArgumentAccess for analytics or logging:

    event(new PaginatorPageChanged($currentPage, $totalPages));
    
  3. Localization Components support localization via Laravel’s translation system. Override default strings in lang/en/knp-components.php:

    return [
        'paginator' => [
            'previous' => '« Previous',
            'next' => 'Next »',
        ],
    ];
    
  4. Performance Optimization (v5.2.0)

    • For paginators, ensure your total() method does not include ORDER BY clauses to avoid performance degradation:
      // Example: Avoid this in your total() query
      YourModel::orderBy('id')->count();
      
      // Instead, rely on the component's optimized count logic
      

NO_UPDATE_NEEDED would not apply here due to the meaningful changes in v5.2.0.
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.
bugban/symfony
beyonder-capi/workflow-extensions-bundle
beyonder-capi/job-queue-bundle
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin