$ show valor-software/ng2-dragula
This repository provides an Angular wrapper for the dragula drag-and-drop library. It exposes a directive (`[dragula]`) to mark containers as part of a drag group, and a singleton service (`DragulaService`) to configure groups and subscribe to typed RxJS observables for all dragula events. The library supports two-way model binding (`[(dragulaModel)]`) to synchronize dragged data with component arrays, and offers a plugin system for mock drake objects during testing. The architecture cleanly separates concerns: the directive handles DOM registration and model updates, while the service manages group lifecycle and event relay from native dragula callbacks to Angular Observables. It is built with Nx monorepo tooling and includes a demo application, e2e tests, and CI/CD pipelines for building, testing, and publishing to npm. The codebase demonstrates mature Angular patterns, including proper lifecycle management, subscription handling, and typed event emitters.
The LLM identified 3 files worth highlighting for reuse:
The `DragulaService` is the core event hub that converts native dragula callbacks into typed RxJS Observables. It uses a private `Subject<Dispatch>` and custom pipeable operators (`filterEvent`) to expose methods like `drag()`, `drop()`, `dropModel()`, etc. Each method optionally filters by group name. This decouples event consumption from the underlying library and enables Angular-style subscription management. The service also manages group creation/destruction and model handling (cloning, removal, drop). Its design demonstrates a clean adapter pattern for wrapping imperative APIs into reactive streams.
`MockDrake` implements the `DrakeWithModels` interface to simulate dragula drake instances for unit testing. It provides an `emit()` method to manually fire events (e.g., drag, drop, remove) that the `DragulaService` consumes. The mock tracks event subscriptions via an internal `Subject` and mirrors the real drake's event signature. This allows testing of Angular components that depend on dragula without browser-level drag interactions. The design is reusable for mocking any event emitter with typed listeners.
`DrakeFactory` is an injectable factory that creates drake instances (by default using the dragula library). By substituting a mock factory in tests (e.g., `MockDrakeFactory`), the entire drag system can be controlled without real DOM manipulation. This demonstrates a straightforward application of the factory pattern for testability, and could be extracted as a pattern for wrapping third-party constructors with Angular DI.