Blazor ComboBox - Add Search Text Box in HeaderTemplate

Hi,

I am working with Multi-Column Combo boxes and would like to implement a separate Search Text Box just above the dropdown list so that I can do manual filtering.  I know that the recommended approach is to use the ComboBox  Filtering event.  However, that requires me to enter the search text in the Combo Box which is limited to the field chosen as the "Text" field in the ComboBoxFieldSettings.  

I would prefer to have a free-text search field that I can type anything into and then define my own filter routine.  The following code sample allows me to add an SfTextBox into the HeaderTemplate of the ComboBox.  However, I cannot work out how to make this text box editable.

Can you please advise if it is possible to do this?



Following is my code (also see attached solution)

@page "/ComboBox"


@using Syncfusion.Blazor.DropDowns
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Inputs
@inherits OwningComponentBase;
<div class="col-lg-12 control-section">
    <div class="control-wrapper">
        <h3 style="color: red">****I WOULD LIKE TO BE ABLE TO EDIT TEXT IN THE "Filter For" TEXT BOX</h3>
        <label class="example-label">Select a country</label>
        <SfComboBox @ref="Combo" TValue="string" TItem="Countries" Placeholder="e.g. Australia" AllowFiltering="true" DataSource="@Country">
            <ComboBoxFieldSettings Text="Code" Value="Code"/>
            <ComboBoxTemplates TItem="Countries">
                <HeaderTemplate>
                    @****THIS TEXT BOX IS NOT EDITABLE WHEN RENDERED*****@
                    <SfTextBox @bind-Value="searchText" Placeholder="Filter For" Width="100%" OnChange="OnSearchChange"></SfTextBox>
                    <table>
                        <tr>
                            <th width="75px">Code</th>
                            <th width="400px">Name</th>
                        </tr>
                    </table>
                </HeaderTemplate>
                <ItemTemplate Context="luContext">
                    <table>
                        <tbody>
                        <tr>
                            <td width="50px">@((luContext as Countries).Code)</td>
                            <td width="300px">@((luContext as Countries).Name)</td>
                        </tr>
                        </tbody>
                    </table>
                </ItemTemplate>
            </ComboBoxTemplates>
        </SfComboBox>
    </div>
</div>
<style>
    .control-wrapper {
        max-width: 250px;
        margin: 0 auto;
        padding: 50px 0px 0px;
    }
    .example-label {
        font-size: 14px;
        margin-bottom: 6px;
    }
</style>
@code{
    private SfComboBox<string, Countries> Combo { get; set; }


    public class Countries
    {
        public string Name { get; set; }
        public string Code { get; set; }
    }
    private List<Countries> Country = new List<Countries>
    {
        new Countries() { Name = "Australia", Code = "AU" },
        new Countries() { Name = "Bermuda", Code = "BM" },
        new Countries() { Name = "Canada", Code = "CA" },
        new Countries() { Name = "Cameroon", Code = "CM" },
        new Countries() { Name = "Denmark", Code = "DK" },
        new Countries() { Name = "France", Code = "FR" },
        new Countries() { Name = "Finland", Code = "FI" },
        new Countries() { Name = "Germany", Code = "DE" },
        new Countries() { Name = "Greenland", Code = "GL" },
        new Countries() { Name = "Hong Kong", Code = "HK" },
        new Countries() { Name = "India", Code = "IN" },
        new Countries() { Name = "Italy", Code = "IT" },
        new Countries() { Name = "Japan", Code = "JP" },
        new Countries() { Name = "Mexico", Code = "MX" },
        new Countries() { Name = "Norway", Code = "NO" },
        new Countries() { Name = "Poland", Code = "PL" },
        new Countries() { Name = "Switzerland", Code = "CH" },
        new Countries() { Name = "United Kingdom", Code = "GB" },
        new Countries() { Name = "United States", Code = "US" }
    };


    public string? searchText { get; set; }
    public IEnumerable<Countries> Filtered { get; set; }


    private async Task OnSearchChange()
    {
        var query = new Query();


        query.Where(new WhereFilter() {Field = "Name", Operator = "contains", value = searchText, IgnoreCase = true});


        await Combo.FilterAsync(Country, query);


    }


}

Attachment: SyncfusionBlazorApp5ComboBoxSearchBox_c0603746.zip

1 Reply

VJ Vinitha Jeyakumar Syncfusion Team October 3, 2022 12:16 PM UTC

Hi Greg,


If you want to filter the items based on multiple fields, we suggest you to use the ‘Predicate’ in the Filtering event. please check the code below.

Code snippet:
<SfComboBox @ref="comboboxCustomer" ID="CustomerID" TValue="string" TItem="FDICustomer" Placeholder="e.g. Account Num" CssClass="e-multi-column" @bind-Value="@CustAccount" DataSource="@Customers" AllowFiltering="true" Query="@customerQuery" PopupWidth="700px" PopupHeight="500">
    <ComboBoxFieldSettings Text="Name" Value="Name"></ComboBoxFieldSettings>
    <ComboBoxTemplates TItem="FDICustomer">
        <HeaderTemplate>
            <table><tr><th class="e-text-center">Account Number</th><th class="e-text-center">Name</th></tr></table>
        </HeaderTemplate>
        <ItemTemplate Context="context">
            <table><tbody><tr><td class="e-text-center">@((context as FDICustomer).Job)</td><td class="e-text-center">@((context as FDICustomer).Name)</td></tr> </tbody></table>
        </ItemTemplate>
    </ComboBoxTemplates>
    <ComboBoxEvents TValue="string" TItem="FDICustomer" Filtering="onFilteringCustAccount" ></ComboBoxEvents>

</SfComboBox>
public async Task onFilteringCustAccount(Syncfusion.Blazor.DropDowns.FilteringEventArgs args)
    {
        args.PreventDefaultAction = true;

        var pre = new WhereFilter();
        var predicate = new List<WhereFilter>
            ();
        predicate.Add(new WhereFilter() { Condition = "or", Field = "Job", value = args.Text, Operator = "contains", IgnoreAccent = true, IgnoreCase = true });
        predicate.Add(new WhereFilter() { Condition = "or", Field = "Name", value = args.Text, Operator = "contains", IgnoreAccent = true, IgnoreCase = true });
        predicate.Add(new WhereFilter() { Condition = "or", Field = "Code", value = args.Text, Operator = "contains", IgnoreAccent = true, IgnoreCase = true });
        pre = WhereFilter.Or(predicate);

        var query = new Query();
        query = args.Text == "" ? new Query().Take(100) : new Query().Where(pre).Take(100);
        await this.comboboxCustomer.Filter(Customers, query);
    }
  

If it doesn't meet with your requirement, please let us know your concerns

Regards,
Vinitha

Loader.
Up arrow icon