Clear filter text on blur

Hello,

we are using the SfMultiSelect in our application to handle tags. We enabled filtering and custom values.

In general this works great as the user can both easily find existing tags as well as create their own. The problem is when the user enters a filter text and the element get out of focus (clicking tab or outside the dialog). Now the filter text will remain in the dialog. This results in users complaining why the tag was not created/selected and a lot of confusion for the users as they see that the tag text is in the dialog form when they save it later but the value is not applied.

Therefore I would like to be able to clear the currently selected filter text when the user exits the dialog.


Can you please tell me how I can do that?


9 Replies

KP Kokila Poovendran Syncfusion Team October 23, 2024 11:20 AM UTC

Hi VR Voice Custom Solutions Admin


Thank you for reaching out to us regarding the issue with the SfMultiSelect component.

We understand that it can be confusing for users when the filter text remains in the input after it loses focus. To address this, we have prepared a solution that clears the currently selected filter text when the user exits the dialog. Please find the code snippet below:



<SfMultiSelect @ref="MultiSelectObj" TItem="GameFields" ID="Multi" AllowFiltering="true" AllowCustomValue=true TValue="string[]" DataSource="@Games">
<MultiSelectEvents TItem="GameFields" TValue="string[]" Blur="@BlurHandler"></MultiSelectEvents>
<MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
</SfMultiSelect>

@code {
SfMultiSelect<string[],GameFields> MultiSelectObj;

public class GameFields
{
public string ID { get; set; }
public string Text { get; set; }
}

private List<GameFields> Games = new List<GameFields>() {
new GameFields(){ ID= "Game1", Text= "American Football" },
new GameFields(){ ID= "Game2", Text= "Badminton" },
new GameFields(){ ID= "Game3", Text= "Basketball" },
new GameFields(){ ID= "Game4", Text= "Cricket" },
};

private async Task BlurHandler(object args)
{
// Use JavaScript Interop to clear the input value
await JS.InvokeVoidAsync("clearMultiSelectInput");
}
}

javascript:

function clearMultiSelectInput(elementId) {
const inputElement = document.querySelector("#Multi");
if (inputElement) {
inputElement.value = ''; // Clear the input value
}
}


This implementation utilizes the Blur event of the SfMultiSelect to trigger a JavaScript function that clears the input value whenever the input loses focus.

Please give this a try, and let us know if it resolves the issue or if you have any further questions. We’re here to help!



MW Marco Wollschläger October 23, 2024 12:37 PM UTC

Hello Kokila,


thank you for the implementation. I've tried this and the field text will be cleared, but now the floating label does not behave correctly anymore, when no elements will be selected. The placeholder will remain in a top position when FloatLabelType is set to FloatLabelType.Auto


Best regards,
Marco



YS Yohapuja Selvakumaran Syncfusion Team November 20, 2024 12:51 PM UTC

Hi VR Voice Custom Solutions Admin,


Thank you for getting back to us.


We would like to inform you that when the AllowCustomValue property is enabled for the component, the input text is retained in the input field by default. This is the intended behavior of the component.


If you prefer not to maintain the input text, we recommend setting AllowCustomValue to false. By doing so, the input text will not be retained, and the floating label will work as expected when the input field loses focus. Below is a code snippet demonstrating this:


Code Snippet:


 

@using Syncfusion.Blazor.DropDowns

 

<SfMultiSelect @ref="MultiSelectObj" TItem="GameFields" ID="Multi" AllowFiltering="true" AllowCustomValue=false TValue="string[]" DataSource="@Games" Placeholder="Enter the text" FloatLabelType="FloatLabelType.Auto">

    <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>

</SfMultiSelect>

 

@code {

    SfMultiSelect<string[], GameFields> MultiSelectObj;

 

    public class GameFields

    {

        public string ID { get; set; }

        public string Text { get; set; }

    }

 

    private List<GameFields> Games = new List<GameFields>() {

new GameFields(){ ID= "Game1", Text= "American Football" },

new GameFields(){ ID= "Game2", Text= "Badminton" },

new GameFields(){ ID= "Game3", Text= "Basketball" },

new GameFields(){ ID= "Game4", Text= "Cricket" },

};

}

 




Regards,

Yohapuja S



MW Marco Wollschläger November 20, 2024 03:57 PM UTC

Hello Yohapuja,

thank you for the response. As described in the initial message, we require custom values to be able to define new tags when needed. Therefore AllowCustomValues is required.

The solution provided by Kokila worked mostly though label does not behavor correctly.

Of course and official option or method on the multiselect would be be the best solution.

Best



PK Priyanka Karthikeyan Syncfusion Team November 26, 2024 02:18 PM UTC

Hi VR Voice Custom Solutions Admin,

 

Thank you for your patience.

To resolve the label issue, you can call the ClearAsync method on the blur event when no item is selected. If an item is selected, you can use JavaScript Interop to clear the input value. Below is the code snippet demonstrating this solution:

 

 

private async Task BlurHandler(object args)
    {
        if (MultiSelectObj.Value != null) {
            
        // Use JavaScript Interop to clear the input value
        await JS.InvokeVoidAsync("clearMultiSelectInput");
            }
        else
        {
            MultiSelectObj.ClearAsync();
        }
    }

 

 

Regards,

Priyanka K

 

 


Attachment: BlazorAppNew1_5a852528.zip


MW Marco Wollschläger November 26, 2024 03:11 PM UTC

Hello Priyanka,


thank you very much for your help here. This fixes our remaining issue.

I did however spot a strange behavior that is likely not supposed to work like this: For the label to return to the empty state, the parent component has to render. That should not be required as the parent component has no change to process and this forces a lot of logic to run for no reason.

I've attached an example where I simply added ShouldRender and OnAfterRender overrides to simulate an on demand render behavior and provided two multi select boxes to show the differences between rendering the parent component and to not render it.

Best regards,

Marco


Attachment: BlazorAppNew1_modified_b375c565.zip


PK Priyanka Karthikeyan Syncfusion Team December 3, 2024 01:54 PM UTC

Hi VR Voice Custom Solutions Admin,

Thank you for the update. The issue arises because the ShouldRender method is set to conditionally allow rendering only when _somethingChanged is true. When _somethingChanged is set to false, the parent component does not re-render, preventing the label from updating its position correctly after focus out.

If _somethingChanged is set to true, the label correctly moves to the bottom as the component re-renders. This behavior indicates that re-rendering is necessary for the label's position to update properly when the focus changes.

To fix this issue, ensure _somethingChanged is set to true in the BlurHandlerWithRender method, or remove the conditional rendering logic if it's not critical to the application's performance. 

private async Task BlurHandlerWithRender(object args) { if (MultiSelectObjWithRender.Value != null) { // Use JavaScript Interop to clear the input value await JS.InvokeVoidAsync("clearMultiSelectInput", "#MultiWithRender"); } else { await MultiSelectObjWithRender.ClearAsync(); _somethingChanged = true; // Ensure re-rendering occurs } }


Regards,

Priyanka K



VV VR Voice Custom Solutions Admin December 3, 2024 02:01 PM UTC

Hello Priyanka,


first of all, thank you for the response. I'm fully aware of what you said and have already implemented this as a workaround.


Still I do not see the reason for the parent component to require a rendering when the change is isolated to the child component. The label has nothing to do with the parent component after all and a rendering of SfMultiSelect itself should be enough.


Best regards,
Marco



PK Priyanka Karthikeyan Syncfusion Team December 11, 2024 01:59 PM UTC

Hi VR Voice Custom Solutions Admin,

 

Thank you for your update. In the shared sample, you initially set the ShouldRender variable to false, which prevents the re-rendering of the parent component. As a result, when you type text in the first component and then focus out, the label does not move to the bottom as expected.

By setting ShouldRender to true during the Blur event of the second SfMultiSelect component, you force a refresh the UI so it re-render of both the first and second components. This triggers the necessary updates and ensures that the labels are correctly positioned.

 

Why Is Re-rendering of the Parent Component Required?

In Blazor, the ShouldRender method determines whether a component should re-render when its state changes. In your case, setting ShouldRender to true from the Blur event of the second component forces the parent component to re-render. This includes both child components, ensuring that the visual state (like label positions) is correctly updated across all components.

 

The reason the parent component must re-render is because Blazor updates the entire component tree based on the state of the parent. When you manually trigger the re-render, it ensures that the UI reflects the most up-to-date state, including any visual changes in the child components, such as the label floating behavior.

 

We hope this helps clarify why re-rendering is necessary for the parent component. If you have any further questions or need more assistance, please feel free to reach out!

 

Regards,

Priyanka K


Loader.
Up arrow icon