{"id":45901930,"url":"https://github.com/andhxl/blazor-sortable","last_synced_at":"2026-02-27T23:42:06.150Z","repository":{"id":301261689,"uuid":"997089843","full_name":"andhxl/blazor-sortable","owner":"andhxl","description":"A Blazor component that wraps the SortableJS library to provide interactive, drag-and-drop list reordering functionality","archived":false,"fork":false,"pushed_at":"2025-11-17T08:38:54.000Z","size":36804,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-17T09:22:37.416Z","etag":null,"topics":["blazor","components","drag-and-drop","drag-drop","dragdrop","dragndrop","reorder","sortable","sortablejs","ui"],"latest_commit_sha":null,"homepage":"https://andhxl.github.io/blazor-sortable/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andhxl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-06T00:08:54.000Z","updated_at":"2025-11-17T07:47:05.000Z","dependencies_parsed_at":"2025-08-12T15:15:44.962Z","dependency_job_id":"4ac9bcc6-531e-40d6-830b-3b19a5d05a61","html_url":"https://github.com/andhxl/blazor-sortable","commit_stats":null,"previous_names":["andhxl/blazorsortable","andhxl/blazor-sortable"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/andhxl/blazor-sortable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andhxl%2Fblazor-sortable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andhxl%2Fblazor-sortable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andhxl%2Fblazor-sortable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andhxl%2Fblazor-sortable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andhxl","download_url":"https://codeload.github.com/andhxl/blazor-sortable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andhxl%2Fblazor-sortable/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29919258,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"ssl_error","status_checked_at":"2026-02-27T19:37:41.463Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blazor","components","drag-and-drop","drag-drop","dragdrop","dragndrop","reorder","sortable","sortablejs","ui"],"created_at":"2026-02-27T23:42:05.555Z","updated_at":"2026-02-27T23:42:06.143Z","avatar_url":"https://github.com/andhxl.png","language":"C#","readme":"# BlazorSortable\n\n![BlazorSortable Icon](https://raw.githubusercontent.com/andhxl/blazor-sortable/main/icon.png)\n\n[![NuGet Version](https://img.shields.io/nuget/vpre/BlazorSortable?style=for-the-badge)](https://www.nuget.org/packages/BlazorSortable)\n[![NuGet Downloads](https://img.shields.io/nuget/dt/BlazorSortable?style=for-the-badge)](https://www.nuget.org/packages/BlazorSortable)\n\nA Blazor component that wraps the [SortableJS](https://github.com/SortableJS/Sortable) library, designed for creating interactive sortable lists with drag-and-drop support. Inspired by [BlazorSortable](https://github.com/the-urlist/BlazorSortable) and represents an improved and extended implementation.\n\n## Installation\n\n### Via Nuget Package Manager\n\n### Via .NET CLI\n```bash\ndotnet add package BlazorSortable\n```\n\n### Via PackageReference\nAdd to your .csproj file:\n```xml\n\u003cItemGroup\u003e\n  \u003cPackageReference Include=\"BlazorSortable\" Version=\"5.*\" /\u003e\n\u003c/ItemGroup\u003e\n```\n\n## Setup\n\n1. Add the SortableJS library to:\n    - `wwwroot/index.html` (for Blazor WebAssembly)  \n    - `Components/App.razor` (for Blazor Web App)  \n    - `Pages/_Host.cshtml` (for Blazor Server)\n\n    Using one of the following methods:\n\n    a) **Via CDN:**\n    ```html\n    \u003cscript src=\"https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js\"\u003e\u003c/script\u003e\n    ```\n\n    b) **Locally:**\n    ```html\n    \u003cscript src=\"lib/sortable/dist/js/Sortable.min.js\"\u003e\u003c/script\u003e\n    ```\n    \u003e You can optionally include a version parameter to avoid browser caching:\n    \u003e ```html\n    \u003e \u003cscript src=\"lib/sortable/dist/js/Sortable.min.js?v=1.15.6\"\u003e\u003c/script\u003e\n    \u003e ```\n\n    For local installation:\n    1. Download the latest version of SortableJS from [GitHub](https://github.com/SortableJS/Sortable/releases)\n    2. Create the folder structure in `wwwroot`: `lib/sortable/dist/js/`\n    3. Place the `Sortable.min.js` file in the created folder\n\n2. (Optional) Add base styles to the same file where you added the script:\n```html\n\u003clink rel=\"stylesheet\" href=\"_content/BlazorSortable/css/blazor-sortable.css\" /\u003e\n```\n\u003e You can also specify the version manually to prevent browser caching:\n\u003e ```html\n\u003e \u003clink rel=\"stylesheet\" href=\"_content/BlazorSortable/css/blazor-sortable.css?v=5.2.1\" /\u003e\n\u003e ```\n\u003e Or automatically insert the current assembly version (works in `.razor` or `.cshtml` files).\n\u003e Add this code within the `\u003chead\u003e` element, or for **Blazor WebAssembly**, place it inside the `\u003cHeadContent\u003e` section of `App.razor`:\n\u003e ```razor\n\u003e \u003clink rel=\"stylesheet\" href=\"_content/BlazorSortable/css/blazor-sortable.css?v=@(typeof(BlazorSortable.Sortable\u003c\u003e).Assembly.GetName().Version)\" /\u003e\n\u003e ```\n\u003e \u003e For this to work in **Blazor WebAssembly**, make sure you have the following line in your `Program.cs`:\n\u003e \u003e ```csharp\n\u003e \u003e builder.RootComponents.Add\u003cHeadOutlet\u003e(\"head::after\");\n\u003e \u003e ```\n\n3. Add services in `Program.cs`:\n```csharp\nusing BlazorSortable;\n\n// ...\n\nbuilder.Services.AddSortable();\n```\n\n4. Add the using directive in `_Imports.razor`:\n```razor\n@using BlazorSortable\n```\n\n## Usage Examples\n\n```razor\n\u003cSortable Items=\"Persons\"\n          Class=\"my-sortable\"\n          Group=\"group1\"\u003e\n    \u003cPersonComponent Person=\"context\" /\u003e\n\u003c/Sortable\u003e\n```\n\n```razor\n\u003cSortable TItem=\"Person\"\n          Items=\"Persons\"\n          Class=\"my-sortable\"\n          Group=\"group1\"\n          Context=\"person\"\u003e\n    \u003cdiv class=\"person-card\"\u003e\n        \u003ch4\u003e@person.Name\u003c/h4\u003e\n        \u003cp\u003e@person.Email\u003c/p\u003e\n        \u003cspan class=\"badge\"\u003e@person.Department\u003c/span\u003e\n    \u003c/div\u003e\n\u003c/Sortable\u003e\n```\n\n```razor\n\u003cSortable TItem=\"object\"\n          Class=\"my-sortable-drop-zone\"\n          Group=\"group1\" /\u003e\n```\n\n## Component Parameters\n\n### Sortable\n\n\u003e **Note:** Support for MultiDrag and Swap plugins will be added in future releases.\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `TItem` | — | — | The type of items in the list |\n| `Items` | `IList\u003cTItem\u003e?` | `null` | List of items to display and sort |\n| `ChildContent` | `RenderFragment\u003cTItem\u003e?` | `null` | Template for displaying each list item. Can be a component, HTML elements, or any Razor markup |\n| `KeySelector` | `Func\u003cTItem, object\u003e?` | `null` | Function for generating the key used in `@key`. If not set, the item itself is used |\n| `Context` | `string` | `context` | Name of the parameter used in the child content template to refer to the current item |\n| `Class` | `string?` | `null` | CSS class for the container |\n| `Style` | `string?` | `null` | Inline CSS styles for the container |\n| `Attributes` | `IReadOnlyDictionary\u003cstring, object\u003e?` | `null` | Additional custom attributes that will be rendered by the component |\n| `Id` | `string` | `Random GUID` | Unique identifier of the component. Used internally for coordination between Sortable components. Must be globally unique |\n| `Group` | `string` | `Random GUID` | Name of the group for interacting with other sortable instances |\n| `Pull` | `SortablePullMode?` | `null` | Mode for pulling items from the list |\n| `PullGroups` | `string[]?` | `null` | **Required when `Pull=\"SortablePullMode.Groups\"`.** Specifies the groups into which items from this list can be dragged |\n| `CloneFunction` | `Func\u003cTItem, TItem\u003e?` | `null` | **Required when `Pull=\"SortablePullMode.Clone\"`.** A factory method used to create a clone of the dragged item |\n| `PullFunction` | `Predicate\u003cSortableTransferContext\u003cTItem\u003e\u003e?` | `null` | **Required when `Pull=\"SortablePullMode.Function\"`.** Function to determine if an item can be pulled to the target Sortable component. **Works only in Blazor WebAssembly** |\n| `Put` | `SortablePutMode?` | `null` | Mode for adding items to the list |\n| `PutGroups` | `string[]?` | `null` | **Required when `Put=\"SortablePutMode.Groups\"`.** Specifies the groups from which items are allowed to be added |\n| `PutFunction` | `Predicate\u003cSortableTransferContext\u003cobject\u003e\u003e?` | `null` | **Required when `Put=\"SortablePutMode.Function\"`.** Function to determine if an item can be put into this list. **Works only in Blazor WebAssembly** |\n| `ConvertFunction` | `Func\u003cSortableTransferContext\u003cobject\u003e, TItem?\u003e?` | `null` | Function to convert items from other Sortable component to the target type |\n| `Sort` | `bool` | `true` | Enables or disables sorting of items within the list |\n| `Delay` | `int` | `0` | Time in milliseconds to define when the sorting should start. Unfortunately, due to browser restrictions, delaying is not possible on IE or Edge with native drag and drop |\n| `DelayOnTouchOnly` | `bool` | `false` | Whether or not the delay should be applied only if the user is using touch (eg. on a mobile device). No delay will be applied in any other case |\n| `TouchStartThreshold` | `int` | `0` | This option sets the minimum pointer movement that must occur before the delayed sorting is cancelled. Values between `3` to `5` are good |\n| `Disabled` | `bool` | `false` | Disables the Sortable component when set to true |\n| `Animation` | `int` | `150` | Animation duration in milliseconds |\n| `Handle` | `string?` | `null` | CSS selector for elements that can be dragged (e.g. `.my-handle`) |\n| `Filter` | `string?` | `null` | CSS selector for elements that cannot be dragged (e.g. `.ignore-elements`) |\n| `DraggableSelector` | `Predicate\u003cTItem\u003e?` | `null` | Function to determine if an item can be dragged |\n| `DraggableClass` | `string` | `\"sortable-draggable\"` | CSS class applied to items that can be dragged |\n| `GhostClass` | `string` | `\"sortable-ghost\"` | CSS class for the placeholder during drag |\n| `ChosenClass` | `string` | `\"sortable-chosen\"` | CSS class for the chosen element |\n| `DragClass` | `string` | `\"sortable-drag\"` | CSS class for the dragged element |\n| `SwapThreshold` | `double` | `1` | Percentage of the target that the swap zone will take up, as a float between `0` and `1` |\n| `InvertSwap` | `bool` | `false` | Set to true to set the swap zone to the sides of the target, for the effect of sorting \"in between\" items |\n| `InvertedSwapThreshold` | `double` | `1` | Percentage of the target that the inverted swap zone will take up, as a float between `0` and `1` |\n| `ForceFallback` | `bool` | `true` | If set to true, the Fallback for non HTML5 Browser will be used, even if we are using an HTML5 Browser |\n| `FallbackClass` | `string` | `\"sortable-fallback\"` | CSS class for the element in fallback mode |\n| `FallbackOnBody` | `bool` | `false` | Appends the cloned DOM Element into the Document's Body |\n| `FallbackTolerance` | `int` | `0` | Emulates the native drag threshold. Specify in pixels how far the mouse should move before it's considered as a drag. `3` to `5` are probably good values |\n| `Scroll` | `bool` | `true` | Enables scrolling of the container during dragging |\n| `OnUpdate` | `Action\u003cSortableEventArgs\u003cTItem\u003e\u003e?` | `null` | Raised when the order of items is changed |\n| `OnAdd` | `Action\u003cSortableEventArgs\u003cTItem\u003e\u003e?` | `null` | Raised when an item is added to the list |\n| `OnRemove` | `Action\u003cSortableEventArgs\u003cTItem\u003e\u003e?` | `null` | Raised when an item is removed from the list |\n\n### SortablePullMode\n\n| Value | Description |\n|-------|-------------|\n| `True` | Allows pulling items from the list |\n| `False` | Prohibits pulling items from the list |\n| `Groups` | Allows pulling items only from specified groups (requires `PullGroups` parameter) |\n| `Clone` | Creates a clone of the item when dragging (requires `CloneFunction` parameter) |\n| `Function` | Uses a custom function to determine if items can be pulled (requires `PullFunction` parameter) |\n\n### SortablePutMode\n\n| Value | Description |\n|-------|-------------|\n| `True` | Allows adding items to the list |\n| `False` | Prohibits adding items to the list |\n| `Groups` | Allows adding items only from specified groups (requires `PutGroups` parameter) |\n| `Function` | Uses a custom function to determine if items can be added (requires `PutFunction` parameter) |\n\n## Events\n\nAll events receive a `SortableEventArgs\u003cTItem\u003e` parameter.  \nFunctions like `PullFunction`, `PutFunction` and `ConvertFunction` use a `SortableTransferContext\u003cTItem\u003e` parameter.\n\n### SortableEventArgs\n\nThe `SortableEventArgs\u003cTItem\u003e` class provides information about sorting operations.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `Item` | `TItem` | The item participating in the operation |\n| `From` | `ISortableInfo` | Source sortable component |\n| `OldIndex` | `int` | The previous index of the item in the source sortable |\n| `To` | `ISortableInfo` | Target sortable component |\n| `NewIndex` | `int` | The new index of the item in the target sortable |\n| `IsClone` | `bool` | Flag indicating whether the item is a clone |\n| `Cancel` | `bool` | Gets or sets a value indicating whether the current operation should be cancelled |\n\n### SortableTransferContext\n\nThe `SortableTransferContext\u003cTItem\u003e` class represents the context of transferring an item between sortable components.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `Item` | `TItem` | The item being transferred between sortable components |\n| `From` | `ISortableInfo` | The source sortable component |\n| `To` | `ISortableInfo` | The target sortable component |\n\n### ISortableInfo\n\nThe `ISortableInfo` interface provides information about a sortable component.\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `Id` | `string` | Unique identifier of the component |\n| `Group` | `string` | Group name for interaction with other Sortable components |\n\n## Notes\n\n- **Order of events when dragging between lists:**\n  1. `OnAdd` is triggered **first** — during this event, the item is **still present in the source list**.\n  2. `OnRemove` is triggered **after**.\n\n- **Cancelling operations:**  \n  Inside `OnUpdate`, `OnAdd` and `OnRemove` handlers you can cancel the operation by setting `args.Cancel = true`.\n\n- **Events use `Action\u003cT\u003e?` instead of `EventCallback\u003cT\u003e`.**  \n  **Reason:** `EventCallback.InvokeAsync` automatically triggers `ComponentBase.StateHasChanged` in the parent component, which causes conflicts between the DOM and the data model for this component.\n\n- **Type mismatch / failed conversion:**  \n  If item types don’t match or the `ConvertFunction` returns `null`, the item is **not added** to the target list and is **remains in its original position**.\n\n- **Dragging issues on scrolled page:**  \n  If the dragged element appears misaligned when the page is scrolled, set\n  ```razor\n  ForceFallback=\"false\"\n  ```\n  **or**\n  ```razor\n  FallbackOnBody=\"true\"\n  ```\n\n- **Blazor Server limitation:**  \n  `PullFunction` and `PutFunction` require synchronous JS-to-.NET calls used by Sortable.js,\n  which are only available in **Blazor WebAssembly**.\n  On Blazor Server these functions cannot work and will throw `NotSupportedException`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandhxl%2Fblazor-sortable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandhxl%2Fblazor-sortable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandhxl%2Fblazor-sortable/lists"}