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

Sortable Ui Bundle Laravel Package

aliocza/sortable-ui-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to Enable Sortable UI

  1. Install Dependencies

    composer require aliocza/sortable-ui-bundle
    composer require gedmo/doctrine-extensions stof/doctrine-extensions-bundle
    
  2. Enable Bundles in app/AppKernel.php:

    new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
    new Aliocza\SortableUiBundle\AlioczaSortableUiBundle(),
    
  3. Configure Doctrine Extensions in config.yml:

    stof_doctrine_extensions:
        orm:
            default:
                sortable: true
    
  4. Add Position Field to your entity (e.g., Client):

    use Gedmo\Mapping\Annotation as Gedmo;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity
     */
    class Client
    {
        /**
         * @Gedmo\SortablePosition
         * @ORM\Column(type="integer")
         */
        private $position;
    }
    
  5. Register the Sortable Listener in services.yml:

    services:
        gedmo.listener.sortable:
            class: Gedmo\Sortable\SortableListener
            tags:
                - { name: doctrine.event_subscriber, connection: default }
            calls:
                - [ setAnnotationReader, [ "@annotation_reader" ] ]
    
  6. Configure Bundle in config.yml:

    aliocza_sortable_ui:
        db_driver: orm
        position_field:
            default: position
            entities:
                AppBundle\Entity\Client: position
    
  7. Integrate into Sonata Admin (ClientAdmin.php):

    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->add('_action', 'actions', [
                'actions' => [
                    'drag' => [
                        'template' => 'AlioczaSortableUiBundle:Default:drag.html.twig'
                    ]
                ]
            ]);
    }
    
  8. Override Base Template in ClientAdmin.php:

    public function configure()
    {
        $this->setTemplate('list', 'AlioczaSortableUiBundle:CRUD:base_list.html.twig');
    }
    
  9. Add Route in ClientAdmin.php:

    protected function configureRoutes(RouteCollection $collection)
    {
        $collection->add('drag', 'drag');
    }
    
  10. Inject Position Service in services.yml:

    app.admin.client:
        class: AppBundle\Admin\ClientAdmin
        arguments: [...]
        calls:
            - [ setPositionService, ['@aliocza_sortable_ui.position'] ]
    

First Use Case: Sortable Client List

  • After setup, the Sonata admin list for Client will include a drag handle (🖱️ icon) in each row.
  • Drag rows to reorder them—positions are saved automatically via AJAX.
  • Verify changes in the database (position column updates).

Implementation Patterns

Workflow: Integrating with Sonata Admin

  1. Entity Setup

    • Add @Gedmo\SortablePosition to the field you want to sort by (e.g., position, order).
    • Ensure the field is an integer type.
  2. Admin Configuration

    • Extend configureListFields() to include the drag action:
      $listMapper->add('_action', 'actions', ['actions' => ['drag' => [...]]]);
      
    • Override the base list template to AlioczaSortableUiBundle:CRUD:base_list.html.twig.
  3. Routing

    • Declare a drag route in configureRoutes() to handle AJAX updates:
      $collection->add('drag', 'drag');
      
  4. Service Injection

    • Inject PositionHandler into your admin class to customize sorting logic:
      public function setPositionService(PositionHandler $positionHandler) {
          $this->positionService = $positionHandler;
      }
      
  5. Customization

    • Override Twig templates (e.g., drag.html.twig) to modify the drag handle UI.
    • Extend PositionHandler to add business logic (e.g., validation before saving).

Integration Tips

  • Multi-Entity Support: Configure position_field.entities in config.yml to map different fields per entity.
  • Default Sorting: Set datagridValues in your admin to default-sort by the position field:
    protected $datagridValues = [
        '_sort_by' => 'position',
        '_sort_order' => 'ASC',
    ];
    
  • Batch Updates: Use the PositionHandler to update positions in bulk (e.g., after a mass action).
  • Event Listeners: Hook into preUpdate/postUpdate events to trigger side effects (e.g., recalculating dependent fields).

Gotchas and Tips

Pitfalls

  1. Missing Doctrine Extensions

    • Forgetting to enable stof_doctrine_extensions or register the SortableListener will cause silent failures.
    • Fix: Verify stof_doctrine_extensions.orm.default.sortable: true and the listener service is defined.
  2. Incorrect Position Field Type

    • The field must be integer. Using string or other types will break sorting.
    • Fix: Update the field type in your entity:
      @ORM\Column(type="integer")
      
  3. Route Conflicts

    • The drag route may conflict with existing routes (e.g., sonata_admin routes).
    • Fix: Use _sonata_admin prefix or customize the route path:
      $collection->add('drag', '_sonata_admin/drag', ['FOSRest' => true]);
      
  4. Caching Issues

    • Sonata’s cache may not reflect changes immediately after reordering.
    • Fix: Clear the cache or use sonata.cache.clear command:
      php bin/console cache:clear
      
  5. JavaScript Errors

    • The drag functionality relies on jQuery UI Sortable. Missing dependencies will break it.
    • Fix: Ensure jquery-ui is included in your admin template:
      {{ sonata_admin_include_jquery_ui('sortable') }}
      

Debugging Tips

  1. Check Database Updates

    • Verify the position field updates in the database after dragging:
      SELECT id, position FROM clients ORDER BY position;
      
  2. Enable Debug Mode

    • Set APP_DEBUG=true in .env to see Symfony errors during drag operations.
  3. Log AJAX Requests

    • Inspect the network tab in browser dev tools for failed AJAX calls to /drag endpoint.
    • Fix: Ensure the PositionHandler is properly injected and the route is accessible.
  4. Validate Entity Changes

    • Override preUpdate in your entity to log position changes:
      public function preUpdate()
      {
          \Log::info('Position updated to: ' . $this->position);
      }
      

Extension Points

  1. Custom Position Logic

    • Extend Aliocza\SortableUiBundle\Services\PositionHandler to add validation or custom save logic:
      class CustomPositionHandler extends PositionHandler
      {
          public function updatePosition($entity, $position)
          {
              if ($position < 0) {
                  throw new \RuntimeException('Position cannot be negative');
              }
              parent::updatePosition($entity, $position);
          }
      }
      
    • Register the service in services.yml:
      services:
          aliocza_sortable_ui.position:
              class: AppBundle\Services\CustomPositionHandler
      
  2. Multi-Level Sorting

    • The bundle lacks multi-level drag-and-drop (as noted in the README). To implement this:
      • Use nested Sortable fields in your entity (e.g., parent_id + position).
      • Customize the Twig template to support nested lists.
  3. Performance Optimization

    • For large datasets, batch updates to reduce database writes:
      // In PositionHandler
      public function updatePositions(array $updates)
      {
          $em = $this->getEntityManager();
          foreach ($updates as $entity) {
              $em->persist($entity);
          }
          $em->flush(); // Single flush for all updates
      }
      
  4. Alternative Drivers

    • The bundle only supports orm driver. For MongoDB, you’d need to:
      • Fork the bundle and implement mongodb driver logic.
      • Extend PositionHandler to use DoctrineMongoDBBundle instead.
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware