Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sortable List Component #636

Merged
merged 20 commits into from
Apr 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"twitter": "//twitter.com/blazorbootstrap",
"github_issues": "//github.com/vikramlearning/blazorbootstrap/issues",
"github_discussions": "//github.com/vikramlearning/blazorbootstrap/discussions",
"stackoverflow": "//stackoverflow.com/questions/tagged/blazorbootstrap"
"stackoverflow": "//stackoverflow.com/questions/tagged/blazor-bootstrap"
}
}
4 changes: 4 additions & 0 deletions BlazorBootstrap.Demo.RCL/BlazorBootstrap.Demo.RCL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
<ProjectReference Include="..\blazorbootstrap\BlazorBootstrap.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Pages\SortableList\" />
</ItemGroup>

<Target Name="EmbedDemos" BeforeTargets="PrepareForBuild">
<!-- Let's embed demos sources into the assembly to show the source at runtime. -->
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<h1>Blazor Charts</h1>
<div class="lead mb-3">
Blazor Bootstrap charts are well-designed chart components on top of Chart.js to visualize data. It contains a rich UI gallery of charts that cater to all charting scenarios. Its high performance helps render large amounts of data quickly.
Blazor Bootstrap charts are well-designed chart components on top of <b>Chart.js</b> to visualize data. It contains a rich UI gallery of charts that cater to all charting scenarios. Its high performance helps render large amounts of data quickly.
</div>

<CarbonAds />
Expand Down
25 changes: 15 additions & 10 deletions BlazorBootstrap.Demo.RCL/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/callout">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.StickyFill" class="me-2" /> Callout <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.StickyFill" class="me-2" /> Callout</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand Down Expand Up @@ -97,7 +97,7 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/currency-input">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.CurrencyDollar" class="me-2" /> Currency Input <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.CurrencyDollar" class="me-2" /> Currency Input</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand All @@ -122,7 +122,7 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/number-input">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.InputCursor" class="me-2" /> Number Input <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.InputCursor" class="me-2" /> Number Input</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand Down Expand Up @@ -157,7 +157,7 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/range-input">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.Sliders" class="me-2" /> Range Input <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.Sliders" class="me-2" /> Range Input</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand All @@ -172,7 +172,12 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/sidebar2">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ListNested" class="me-2" /> Sidebar 2 <Badge Color="BadgeColor.Danger">New</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ListNested" class="me-2" /> Sidebar 2</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/sortable-list">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ArrowsMove" class="me-2" /> Sortable List <Badge Color="BadgeColor.Danger">Preview</Badge></h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand Down Expand Up @@ -202,7 +207,7 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/tooltips">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ChatSquareDotsFill" class="me-2" /> Tooltips <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.ChatSquareDotsFill" class="me-2" /> Tooltips</h4>
</a>
</div>
</div>
Expand All @@ -221,7 +226,7 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/currency-input">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.CurrencyDollar" class="me-2" /> Currency Input <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.CurrencyDollar" class="me-2" /> Currency Input</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand All @@ -231,12 +236,12 @@
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/number-input">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.InputCursor" class="me-2" /> Number Input <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.InputCursor" class="me-2" /> Number Input</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/form/range-input">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.Sliders" class="me-2" /> Range Input <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.Sliders" class="me-2" /> Range Input</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand All @@ -260,7 +265,7 @@
<div class="row g-3 mt-5">
<div class="col-sm-4 mb-2">
<a class="d-block pe-lg-4 text-decoration-none lh-sm" href="/charts/bar-chart">
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.BarChartFill" class="me-2" /> Bar Chart <Badge Color="BadgeColor.Success">Updated</Badge></h4>
<h4 class="mb-0 fs-5 fw-semibold"><Icon Name="IconName.BarChartFill" class="me-2" /> Bar Chart</h4>
</a>
</div>
<div class="col-sm-4 mb-2">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@page "/sortable-list"

<PageTitle>@title</PageTitle>

<MetaTags PageUrl="@pageUrl" Title="@title" Description="@description" ImageUrl="@imageUrl" />

<h1>Blazor Sortable List</h1>
<div class="lead mb-3">
The Blazor Bootstrap Sortable List component, built on top of <b>SortableJS</b>, enables drag-and-drop reordering of lists.
</div>

@* <CarbonAds /> *@

<SectionHeading Size="HeadingSize.H2" Text="Examples" PageUrl="@pageUrl" HashTagName="examples" />
<div class="mb-3"></div>
<Demo Type="typeof(SortableList_Demo_01_Examples)" Tabs="true" />

<SectionHeading Size="HeadingSize.H2" Text="Shared lists" PageUrl="@pageUrl" HashTagName="shared-lists" />
<div class="mb-3">
<p>To drag-and-drop an item from one list to the other and vice versa, set the <b>Group</b> parameter for all the lists. Providing the same <b>Group</b> name for the lists is what links them together.</p>
<p>In the below example, both lists use the same <b>Group</b>.</p>
</div>
<Demo Type="typeof(SortableList_Demo_02_Shared_Lists_A)" Tabs="true" />

<div class="my-3">
In the following example, all three lists use the same group.
</div>
<Demo Type="typeof(SortableList_Demo_02_Shared_Lists_B_Three_Lists)" Tabs="true" />

<SectionHeading Size="HeadingSize.H2" Text="Cloning" PageUrl="@pageUrl" HashTagName="cloning" />
<div class="mb-3">
By setting <code>Pull="SortableListPullMode.Clone"</code>, you can enable item cloning. Drag an item from one list to another to create a copy that stays in the original list.
</div>
<Demo Type="typeof(SortableList_Demo_03_Cloning)" Tabs="true" />

<SectionHeading Size="HeadingSize.H2" Text="Disable sorting" PageUrl="@pageUrl" HashTagName="disable-sorting" />
<div class="mb-3">
You can disable list sorting by setting <code>AllowSorting="false"</code>. In the example below, the list cannot be sorted.
</div>
<Demo Type="typeof(SortableList_Demo_04_Disable_Sorting)" Tabs="true" />

<SectionHeading Size="HeadingSize.H2" Text="Handle" PageUrl="@pageUrl" HashTagName="handle" />
<div class="mb-3">
The <b>Handle</b> parameter specifies the CSS class that denotes the drag handle. In the example below, items can only be sorted by dragging the handle itself.
</div>
<Demo Type="typeof(SortableList_Demo_05_Handle)" Tabs="true" />

<SectionHeading Size="HeadingSize.H2" Text="Disable item" PageUrl="@pageUrl" HashTagName="disable-item" />
<div class="mb-3">
Try dragging the red-backgrounded item. You won't be able to, as it's disabled using the <b>DisableItem</b> parameter.
</div>
<Demo Type="typeof(SortableList_Demo_06_Disable_Item)" Tabs="true" />


<SectionHeading Size="HeadingSize.H2" Text="Nested sortables" PageUrl="@pageUrl" HashTagName="nested-sortables" />
@* <div class="mb-3"></div>
<Demo Type="typeof(SortableList_Demo_07_Nested_Sortables)" Tabs="true" /> *@
<Callout Type="CalloutType.Warning" HideHeading="true">
<div>Nested list sorting is not currently supported. We will add this feature in upcoming releases.</div>
</Callout>

<SectionHeading Size="HeadingSize.H2" Text="Dynamic data" PageUrl="@pageUrl" HashTagName="dynamic-data" />
<div class="mb-3"></div>
<Demo Type="typeof(SortableList_Demo_08_Dynamic_Data)" Tabs="true" />

<SectionHeading Size="HeadingSize.H2" Text="Empty data" PageUrl="@pageUrl" HashTagName="empty-data" />
<div class="mb-3"></div>
<Demo Type="typeof(SortableList_Demo_09_Empty_Data)" Tabs="true" />

@code {
private string pageUrl = "/sortable-list";
private string title = "Blazor Sortable List Component";
private string description = "The Blazor Bootstrap Sortable List component, built on top of SortableJS, enables drag-and-drop reordering of lists.";
private string imageUrl = "https://i.imgur.com/bfzP8Yi.png";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<SortableList TItem="Employee"
Data="employees"
Context="item"
OnUpdate="@OnEmployeeListUpdate">
<ItemTemplate>
@item.Name
</ItemTemplate>
</SortableList>

@code {
public List<Employee> employees = Enumerable.Range(1, 5).Select(i => new Employee(i, $"Employee {i}")).ToList();

private void OnEmployeeListUpdate(SortableListEventArgs args)
{
var itemToMove = employees[args.OldIndex];

employees.RemoveAt(args.OldIndex);

if (args.NewIndex < employees.Count)
employees.Insert(args.NewIndex, itemToMove);
else
employees.Add(itemToMove);
}

public record Employee(int Id, string? Name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<div class="row">
<div class="col">
<SortableList TItem="Employee"
Group="SharedListExample2"
Name="empList1"
Data="employeeList1"
Context="item"
OnUpdate="OnEmployeeList1Update"
OnRemove="OnEmployeeList1Remove">
<ItemTemplate>
@item.Name
</ItemTemplate>
</SortableList>
</div>
<div class="col">
<SortableList TItem="Employee"
Group="SharedListExample2"
Name="empList2"
Data="employeeList2"
Context="item"
OnUpdate="OnEmployeeList2Update"
OnRemove="OnEmployeeList2Remove">
<ItemTemplate>
@item.Name
</ItemTemplate>
</SortableList>
</div>
</div>

@code {
public List<Employee> employeeList1 = Enumerable.Range(1, 5).Select(i => new Employee(i, $"Employee {i}")).ToList();

public List<Employee> employeeList2 = Enumerable.Range(6, 5).Select(i => new Employee(i, $"Employee {i}")).ToList();

private void OnEmployeeList1Update(SortableListEventArgs args)
{
var itemToMove = employeeList1[args.OldIndex];

employeeList1.RemoveAt(args.OldIndex);

if (args.NewIndex < employeeList1.Count)
employeeList1.Insert(args.NewIndex, itemToMove);
else
employeeList1.Add(itemToMove);
}

private void OnEmployeeList2Update(SortableListEventArgs args)
{
var itemToMove = employeeList2[args.OldIndex];

employeeList2.RemoveAt(args.OldIndex);

if (args.NewIndex < employeeList2.Count)
employeeList2.Insert(args.NewIndex, itemToMove);
else
employeeList2.Add(itemToMove);
}

private void OnEmployeeList1Remove(SortableListEventArgs args)
{
// get the item at the old index in list 1
var item = employeeList1[args.OldIndex];

// add it to the new index in list 2
employeeList2.Insert(args.NewIndex, item);

// remove the item from the old index in list 1
employeeList1.Remove(employeeList1[args.OldIndex]);
}

private void OnEmployeeList2Remove(SortableListEventArgs args)
{
// get the item at the old index in list 2
var item = employeeList2[args.OldIndex];

// add it to the new index in list 1
employeeList1.Insert(args.NewIndex, item);

// remove the item from the old index in list 2
employeeList2.Remove(employeeList2[args.OldIndex]);
}

public record Employee(int Id, string? Name);
}
Loading
Loading