Skip to content

Commit

Permalink
[SortableList] Adding Properties FromListId and ToListId (#2385)
Browse files Browse the repository at this point in the history
* feat: allow FluentSortableList to know where an item was dragged from and dropped to

* Renamed properties

* Changed example back to two lists

The swapping is still handled differently (getting the list through the ids) than before.

* Reverted to the previous example with added traces for the id.

* Added a test to verify the Id is added to the list

* Renamed the test to clarify intent

* Added unit test for OnUpdate

* Changed parameter names to reflect property names

* Reverted changes made by the IDE

---------

Co-authored-by: Denis Voituron <[email protected]>
  • Loading branch information
RReventlov and dvoituron authored Jul 16, 2024
1 parent f8998c7 commit f8f0e5a
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 14 deletions.
12 changes: 12 additions & 0 deletions examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7959,6 +7959,18 @@
Gets the index of the item in the list after the update.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentSortableListEventArgs.FromListId">
<summary>
Gets the id of the list the item was in before the update.
May be null if no Id was set for <see cref="T:Microsoft.FluentUI.AspNetCore.Components.FluentSortableList`1"/>
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentSortableListEventArgs.ToListId">
<summary>
Gets the id of the list the item is in after the update.
May be null if no Id was set for <see cref="T:Microsoft.FluentUI.AspNetCore.Components.FluentSortableList`1"/>
</summary>
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.FluentSpacer">
<summary />
</member>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@

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

DemoLogger.WriteLine($"Moved item from list {args.FromListId} to list {args.ToListId}");
}

private void ListTwoRemove(FluentSortableListEventArgs args)
Expand All @@ -64,6 +66,8 @@

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

DemoLogger.WriteLine($"Moved item from list {args.FromListId} to list {args.ToListId}");
}
private void SortListOne(FluentSortableListEventArgs args)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Components/SortableList/FluentSortableList.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

@if (ItemTemplate is not null)
{
<div @ref="@Element" class="@ClassValue" style="@StyleValue">
<div @ref="@Element" id="@Id" class="@ClassValue" style="@StyleValue">
@foreach (var item in Items)
{
<div class="sortable-item @(GetItemFiltered(item) ? "filtered" : "")">@ItemTemplate(item)</div>
Expand Down
10 changes: 5 additions & 5 deletions src/Core/Components/SortableList/FluentSortableList.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,22 +126,22 @@ protected bool GetItemFiltered(TItem item)
}

[JSInvokable]
public void OnUpdateJS(int oldIndex, int newIndex)
public void OnUpdateJS(int oldIndex, int newIndex, string fromListId, string toListId)
{
if (OnUpdate.HasDelegate)
{
// invoke the OnUpdate event passing in the oldIndex and the newIndex
OnUpdate.InvokeAsync(new FluentSortableListEventArgs(oldIndex, newIndex));
// invoke the OnUpdate event passing in the oldIndex, the newIndex, the fromId and the toId
OnUpdate.InvokeAsync(new FluentSortableListEventArgs(oldIndex, newIndex, fromListId, toListId));
}
}

[JSInvokable]
public void OnRemoveJS(int oldIndex, int newIndex)
public void OnRemoveJS(int oldIndex, int newIndex, string fromListId, string toListId)
{
if (OnRemove.HasDelegate)
{
// remove the item from the list
OnRemove.InvokeAsync(new FluentSortableListEventArgs(oldIndex, newIndex));
OnRemove.InvokeAsync(new FluentSortableListEventArgs(oldIndex, newIndex, fromListId, toListId));
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Core/Components/SortableList/FluentSortableList.razor.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function init(list, group, pull, put, sort, handle, filter, fallback, com
event.to.insertBefore(event.item, event.to.childNodes[event.oldIndex]);

// Notify .NET to update its model and re-render
component.invokeMethodAsync('OnUpdateJS', event.oldDraggableIndex, event.newDraggableIndex);
component.invokeMethodAsync('OnUpdateJS', event.oldDraggableIndex, event.newDraggableIndex, event.from.id, event.to.id);
},
onRemove: (event) => {
if (event.pullMode === 'clone') {
Expand All @@ -28,7 +28,7 @@ export function init(list, group, pull, put, sort, handle, filter, fallback, com
event.from.insertBefore(event.item, event.from.childNodes[event.oldIndex]);

// Notify .NET to update its model and re-render
component.invokeMethodAsync('OnRemoveJS', event.oldDraggableIndex, event.newDraggableIndex);
component.invokeMethodAsync('OnRemoveJS', event.oldDraggableIndex, event.newDraggableIndex, event.from.id, event.to.id);
}
});
}
16 changes: 15 additions & 1 deletion src/Core/Components/SortableList/FluentSortableListEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ public FluentSortableListEventArgs()

}

public FluentSortableListEventArgs(int oldIndex, int newIndex)
public FluentSortableListEventArgs(int oldIndex, int newIndex, string? fromListId, string? toListId)
{
OldIndex = oldIndex;
NewIndex = newIndex;
FromListId = fromListId;
ToListId = toListId;
}

/// <summary>
Expand All @@ -22,4 +24,16 @@ public FluentSortableListEventArgs(int oldIndex, int newIndex)
/// Gets the index of the item in the list after the update.
/// </summary>
public int NewIndex { get; }

/// <summary>
/// Gets the id of the list the item was in before the update.
/// May be null if no Id was set for <see cref="FluentSortableList{TItem}"/>
/// </summary>
public string? FromListId { get; }

/// <summary>
/// Gets the id of the list the item is in after the update.
/// May be null if no Id was set for <see cref="FluentSortableList{TItem}"/>
/// </summary>
public string? ToListId { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

<div id="list" class="fluent-sortable-list" b-0uum8h8hrq="">
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 1</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 2</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 3</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 4</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 5</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 6</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 7</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 8</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 9</div>
</div>
<div class="sortable-item " b-0uum8h8hrq="">
<div class="sortable-item">Item 10</div>
</div>
</div>
75 changes: 70 additions & 5 deletions tests/Core/SortableList/FluentSortableListTests.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@using Xunit;
@inherits TestContext

@code
{
public class Item
Expand All @@ -23,17 +24,81 @@
public void FluentSortableList_Default()
{
// Arrange && Act
var cut = Render(@<FluentSortableList Items="items">
<ItemTemplate>
<div class="sortable-item">@context.Name</div>
</ItemTemplate>
</FluentSortableList>);
<ItemTemplate>
<div class="sortable-item">@context.Name</div>
</ItemTemplate>
</FluentSortableList>);

// Assert
cut.Verify();
}

[Fact]
public void FluentSortableList_IdIsAdded()
{
// Arrange && Act
var cut = Render(@<FluentSortableList Id="list" Items="items">
<ItemTemplate>
<div class="sortable-item">@context.Name</div>
</ItemTemplate>
</FluentSortableList>);

// Assert
cut.Verify();
}

[Fact]
public void FluentSortableList_OnUpdate()
{
// Arrange
FluentSortableListEventArgs? args = null;
var callback = new EventCallbackFactory().Create<AspNetCore.Components.FluentSortableListEventArgs>
(this, (e => args = e));
var sortableList = new FluentSortableList<Item>()
{
Items = items,
OnUpdate = callback
};

// Act
sortableList.OnUpdateJS(0, 1, "fromList", "toList");

// Verify
Assert.Equal(new FluentSortableListEventArgs(0, 1, "fromList", "toList"), args,
FluentSortableListEventArgsComparer);
}

private static bool FluentSortableListEventArgsComparer(FluentSortableListEventArgs? first, FluentSortableListEventArgs? second)
{
if (first is null || second is null)
{
return false;
}

if (first.FromListId is null || !first.FromListId.Equals(second.FromListId))
{
return false;
}

if (first.ToListId is null || !first.ToListId.Equals(second.ToListId))
{
return false;
}

if (first.OldIndex != second.OldIndex)
{
return false;
}

if (first.NewIndex != second.NewIndex)
{
return false;
}

return true;
}

}

0 comments on commit f8f0e5a

Please sign in to comment.