Skip to content

Commit

Permalink
Autocomplete: Refactor to use DropdownItem ShowCheckbox feature (#5319)
Browse files Browse the repository at this point in the history
* Autocomplete | Refactor to use DropdownItem ShowCheckbox feature

* Experiment with not listening to CheckedChanged and propagating to clickhandler instead

* Revert "Experiment with not listening to CheckedChanged and propagating to clickhandler instead"

This reverts commit 2ee961f.

* Experiment with disabling the checkbox

* Autocomplete : Workaround for checkbox unfocusing TextEdit

* Autocomplete fix tests and fluentui

* Add release notes

* Recompile scss

* Dashboard back to original

---------

Co-authored-by: Mladen Macanovic <[email protected]>
  • Loading branch information
David-Moreira and stsrki authored Feb 27, 2024
1 parent b966d7f commit 7ad4e7e
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,12 @@
Added a new Parameter <Code>DisabledItem</Code>. By defining this, you can set the disabled items from the supplied data source.
</Paragraph>

<Heading Size="HeadingSize.Is3">
Autocomplete
</Heading>

<Paragraph>
We've reworked the <Code>Autocomplete</Code> <Code>SelectionMode.Checkbox</Code> so it more closely follows the standard look of the checkboxes across the application.
</Paragraph>

<NewsPagePostInfo UserName="Mladen Macanović" ImageName="mladen" PostedOn="February 29th, 2024" Read="9 min" />
14 changes: 14 additions & 0 deletions DotnetWatchRunAll.bat
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,18 @@ if %status% == 200 (
cd "%BASE%\Demos\Blazorise.Demo.AntDesign"
start dotnetwatchrun

:antdesign
SET URL="http://localhost:17715"
SET curlCommand=curl -LI %URL% -o /dev/null -w "%%{http_code}" -s
@for /f %%R in ('%curlCommand%') do ( Set status=%%R )

if %status% == 200 (
echo next
) else (
goto antdesign
)

cd "%BASE%\Demos\Blazorise.Demo.FluentUI2"
start dotnetwatchrun

exit
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

.fui-MenuItem.b-is-autocomplete-suggestion {
width: 100%;
display: contents;
display: flex;

&:not(.b-is-autocomplete-suggestion-checkbox) {
display: contents;
}

.fui-MenuItem__content {
&:not([aria-disabled="true"]) {
Expand Down
3 changes: 3 additions & 0 deletions Source/Blazorise.FluentUI2/wwwroot/blazorise.fluentui2.css
Original file line number Diff line number Diff line change
Expand Up @@ -15046,6 +15046,9 @@ span.flatpickr-weekday {
}
.b-is-autocomplete .fui-MenuPopover .fui-MenuList .fui-MenuItem.b-is-autocomplete-suggestion {
width: 100%;
display: flex;
}
.b-is-autocomplete .fui-MenuPopover .fui-MenuList .fui-MenuItem.b-is-autocomplete-suggestion:not(.b-is-autocomplete-suggestion-checkbox) {
display: contents;
}
.b-is-autocomplete .fui-MenuPopover .fui-MenuList .fui-MenuItem.b-is-autocomplete-suggestion .fui-MenuItem__content:not([aria-disabled=true]):focus, .b-is-autocomplete .fui-MenuPopover .fui-MenuList .fui-MenuItem.b-is-autocomplete-suggestion .fui-MenuItem__content:not([aria-disabled=true]):focus-visible {
Expand Down

Large diffs are not rendered by default.

51 changes: 10 additions & 41 deletions Source/Extensions/Blazorise.Components/Autocomplete.razor
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
var item = GetItemByText( selectedText );
var value = GetItemValue( selectedText );
var removeCallback = EventCallback.Factory.Create( this, async () => await RemoveMultipleTextAndValue( selectedText ) );
@TagTemplate(new (item, value, selectedText, removeCallback))
@TagTemplate( new( item, value, selectedText, removeCallback ) )
}
}
}
Expand Down Expand Up @@ -59,20 +59,20 @@
@if ( VirtualizeManualReadMode )
{
<Virtualize @ref="virtualizeRef" TItem="TItem" Context="item" ItemsProvider="VirtualizeItemsProviderHandler">
@itemFragment(item)
@itemFragment( item )
</Virtualize>
}
else if ( Virtualize )
{
<Virtualize @ref="virtualizeRef" TItem="TItem" Context="item" Items="@FilteredData">
@itemFragment(item)
@itemFragment( item )
</Virtualize>
}
else
{
@foreach ( var item in FilteredData ?? Enumerable.Empty<TItem>() )
{
@itemFragment(item)
@itemFragment( item )
}
}
}
Expand All @@ -97,47 +97,17 @@
var itemIndex = FilteredData.IndexOf( item );
var isFocusedItem = itemIndex == ActiveItemIndex;

var isCheckbox = SelectionMode == AutocompleteSelectionMode.Checkbox;

var text = GetItemText( item );
var value = GetItemValue( item );

<DropdownItem @key="@item" ElementId="@DropdownItemId(itemIndex)" Active="@isActiveItem" Class="@DropdownItemClassNames(itemIndex)" Value="@value" Clicked="() => OnDropdownItemSelected(value)">
@if ( SelectionMode == AutocompleteSelectionMode.Checkbox )
{
<Div Flex="Flex.JustifyContent.Start" Margin="Margin.Is1.OnY" Class="@DropdownCheckboxItemClassNames">
<Div Margin="Margin.Is1">
@if ( isActiveItem )
{
<Icon Name="IconName.CheckSquare" TextColor="isFocusedItem ? TextColor.Primary : TextColor.White"></Icon>
}
else
{
<Icon Name="IconName.Square" TextColor="TextColor.Primary"></Icon>
}
</Div>
<Div Margin="Margin.Is1.OnY">
@if ( ItemContent is not null )
{
@ItemContent(new (item, value, text))
}
else
{
@if ( HighlightSearch && Search?.Length > 0 )
{
<Highlighter Text="@text" HighlightedText="@Search" />
}
else
{
@text
}
}
</Div>
</Div>
}
else
{
<DropdownItem @key="@item" ElementId="@DropdownItemId(itemIndex)" Active="@isActiveItem" Checked=@isActiveItem ShowCheckbox=@isCheckbox Class="@DropdownItemClassNames(itemIndex)" Value="@value"
Clicked="() => isCheckbox ? Task.CompletedTask : OnDropdownItemSelected(value)"
CheckedChanged="() => isCheckbox ? OnDropdownItemSelected(value) : Task.CompletedTask">
@if ( ItemContent is not null )
{
@ItemContent(new (item, value, text))
@ItemContent( new( item, value, text ) )
}
else
{
Expand All @@ -150,7 +120,6 @@
@text
}
}
}
</DropdownItem>
};
}
67 changes: 50 additions & 17 deletions Source/Extensions/Blazorise.Components/Autocomplete.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ private class NullableT<T>

private Validation validationRef;

/// <summary>
/// Workaround for the issue where the dropdown closes when clicking on the checkbox
/// </summary>
private bool clickFromCheck;
/// <summary>
/// Workaround for the issue where the dropdown closes when clicking on the checkbox
/// </summary>
private bool focusFromCheck;

#endregion

#region Methods
Expand Down Expand Up @@ -398,6 +407,12 @@ protected async Task OnTextKeyDownHandler( KeyboardEventArgs eventArgs )
/// <returns>Returns awaitable task</returns>
protected async Task OnTextFocusHandler( FocusEventArgs eventArgs )
{
if ( focusFromCheck )
{
focusFromCheck = false;
return;
}

TextFocused = true;
if ( ManualReadMode || MinLength <= 0 )
await Reload();
Expand All @@ -413,28 +428,48 @@ protected async Task OnTextFocusHandler( FocusEventArgs eventArgs )
/// <returns>Returns awaitable task</returns>
protected async Task OnTextBlurHandler( FocusEventArgs eventArgs )
{
await Close();

if ( IsMultiple )
if ( SelectionMode == AutocompleteSelectionMode.Checkbox )
{
await ResetSelected();
await ResetCurrentSearch();
//Workaround for the issue where the dropdown closes when clicking on the checkbox
ExecuteAfterRender( HandleBlurHandler );
}
else
{
if ( !FreeTyping && string.IsNullOrEmpty( SelectedText ) )
await HandleBlurHandler();
}

async Task HandleBlurHandler()
{
if ( clickFromCheck )
{
clickFromCheck = false;
focusFromCheck = true;
await textEditRef.Focus();
return;
}
await Close();

if ( IsMultiple )
{
await ResetSelected();
await ResetCurrentSearch();
return;
}
else
{
if ( !FreeTyping && string.IsNullOrEmpty( SelectedText ) )
{
await ResetSelected();
await ResetCurrentSearch();
return;
}

await SelectedOrResetOnCommit();
}
await SelectedOrResetOnCommit();
}

TextFocused = false;
TextFocused = false;

await SearchBlur.InvokeAsync( eventArgs );
await SearchBlur.InvokeAsync( eventArgs );
}
}

private async Task InvokeSearchChanged( string searchValue )
Expand Down Expand Up @@ -473,8 +508,11 @@ private async Task SelectedOrResetOnCommit()
}
}


private async Task OnDropdownItemSelected( object value )
{
clickFromCheck = ( SelectionMode == AutocompleteSelectionMode.Checkbox );

//TODO : Once Multiple is deprecated we may remove the && !IsMultiple condition
if ( SelectionMode == AutocompleteSelectionMode.Default && !IsMultiple )
{
Expand Down Expand Up @@ -1190,12 +1228,7 @@ protected string DropdownClassNames
/// Gets the custom class-names for dropdown element.
/// </summary>
protected string DropdownItemClassNames( int index )
=> $"b-is-autocomplete-suggestion {( ActiveItemIndex == index ? "focus" : string.Empty )}";

/// <summary>
/// Gets the custom class-names for checkbox element.
/// </summary>
protected string DropdownCheckboxItemClassNames = $"b-is-autocomplete-suggestion-checkbox";
=> $"b-is-autocomplete-suggestion {( ActiveItemIndex == index ? "focus" : string.Empty )} {( SelectionMode == AutocompleteSelectionMode.Checkbox ? "b-is-autocomplete-suggestion-checkbox" : string.Empty )}";

/// <summary>
/// Provides an index based id for the dropdown suggestion items.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#region Using directives

using System.Threading.Tasks;
using Bunit;
using Xunit;

#endregion

namespace Blazorise.Tests.Components;
Expand All @@ -18,7 +20,6 @@ public AutocompleteCheckboxComponentTest()
.AddBlazoriseDropdown();
}


[Fact]
public void Suggestions_ShouldShow_Checkboxes()
{
Expand All @@ -31,7 +32,7 @@ public void Suggestions_ShouldShow_Checkboxes()

var suggestions = comp.FindAll( ".b-is-autocomplete-suggestion" );

Assert.All( suggestions, ( x ) => Assert.True( x.InnerHtml.Contains( "b-is-autocomplete-suggestion-checkbox" ) && x.InnerHtml.Contains( "</i>" ) ) );
Assert.All( suggestions, ( x ) => Assert.Contains( "input", x.InnerHtml ) );
}

[Fact]
Expand All @@ -40,7 +41,6 @@ public void InitialSelectedValues_ShouldSet_SelectedTexts()
TestInitialSelectedValues<AutocompleteCheckboxComponent>( ( comp ) => comp.Instance.SelectedTexts?.ToArray() );
}


[Theory]
[InlineData( new[] { "PT", "HR" }, new[] { "Portugal", "Croatia" } )]
[InlineData( new[] { "CN", "GB" }, new[] { "China", "United Kingdom" } )]
Expand Down

0 comments on commit 7ad4e7e

Please sign in to comment.