Ali
Ali

Reputation: 1235

Mublazor Autocomplete Render Custom HTML

I have to display cities of a country in a Group form, for example my data source is a dictionary like

Country1

City1

City2

City3

Country2

City1

City4

City5

City6

If user search for City2, I need to show Country1 as a heading and then City1 under that heading and If user search for City1, I need to show Country1 and then City and then Country2 and City1

I have done similar thing in Bootstrap and it rendered like

and then I can add css to adjust spaces.

So question is, how can I render customer HTML in Blazor Autocpmplete?

This is what I want to achieve but in Mudblazor autocomplete

 _renderMenu: function (ul, items) {
    var that = this,
        currentCountry = "";
    $.each(items, function (index, item) {
        var li;
        if (item.country != currentCountry) {
            ul.append("<li class='ui-autocomplete-country pl-2 pt-2 font-weight-bold'>" + item.country + "</li>");
            currentCountry = item.country;
        }
        li = that._renderItemData(ul, item);
    });
},
_renderItem: function (ul, item) {
    return $("<li></li>")
        .data("item.autocomplete", item)
        .append('<div class="place-name font-weight-lighter pb-2 pl-3">' + item.city+
            '</br><span class="font-weight-normal" style="font-size:12px;"></span></div>')
        .appendTo(ul);
}

Update 1: Thank you (Fengzhi Zhou) for the answer, I had to make a minor change but I got it working. I added AfterItemsTemplate

<MudAutocomplete T="City" Label="Search City" @bind-Value="selectedCity"
             SearchFunc="@SearchCities" ToStringFunc="@(c => c == null ? null : $"{c.Country} - {c.Name}")">
<ItemTemplate Context="city">
    <MudText>
        @if (previousCountry == null || previousCountry != city.Country)
        {
            <div class="country-heading">@city.Country</div>
            previousCountry = city.Country;
        }
        <div class="city-name">@city.Name</div>
    </MudText>
</ItemTemplate>
<AfterItemsTemplate>
    @{
        previousCountry = null;
    }
</AfterItemsTemplate>

enter image description here

Now the City1 looks like a part of "Country", can I render country as a Separate item and make it disabled?

for example enter image description here

Update 2: I have managed to disable items based on a logic, ItemDisabledFunc="@isDisabled" and then

private bool isDisabled(City city)

{ return true or false based on your logic }

Upvotes: 0

Views: 91

Answers (1)

Fengzhi Zhou
Fengzhi Zhou

Reputation: 1667

If user search for City2, I need to show Country1 as a heading and then City1 under that heading and If user search for City1, I need to show Country1 and then City and then Country2 and City

Based on your description and if I am understanding correctly that you mean "Country1-city2" and then "Country1-city1/Country2-city1" ,MudBlazor has provided the customizing html design.

1. Follow the document to enable MudBlazor in your project.

https://mudblazor.com/getting-started/installation#prerequisites

2. Using ItemTemplate to render customized html elements

@page "/"

<MudGrid>

    <MudItem xs="12" sm="6" md="4">
        <MudAutocomplete T="City" Label="Search City" @bind-Value="selectedCity"
                         SearchFunc="@SearchCities" ToStringFunc="@(c => c == null ? null : $"{c.Country} - {c.Name}")">
            <ItemTemplate Context="city">
                <MudText>
                    @if (previousCountry == null || previousCountry != city.Country)
                    {
                        <div class="country-heading">@city.Country</div>
                    }
                    <div class="city-name">@city.Name</div>
                </MudText>
            </ItemTemplate>
        </MudAutocomplete>
    </MudItem>
</MudGrid>

@code {
    private City selectedCity;
    private string previousCountry = null;

    private List<City> Cities = new List<City>
    {
        new City { Name = "City1", Country = "Country1" },
        new City { Name = "City2", Country = "Country1" },
        new City { Name = "City3", Country = "Country1" },
        new City { Name = "City1", Country = "Country2" },
        new City { Name = "City4", Country = "Country2" },
        new City { Name = "City5", Country = "Country2" },
        new City { Name = "City6", Country = "Country2" },
    };

    private Task<IEnumerable<City>> SearchCities(string value, CancellationToken token)
    {
        if (string.IsNullOrEmpty(value))
            return Task.FromResult<IEnumerable<City>>(Cities);

        var result = Cities.Where(city => city.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase))
                           .OrderBy(city => city.Country)
                           .ThenBy(city => city.Name);
        return Task.FromResult<IEnumerable<City>>(result);
    }

    public class City
    {
        public string Name { get; set; }
        public string Country { get; set; }
    }
}

Here is the doc https://mudblazor.com/components/autocomplete#presentation .

3. Test

enter image description here enter image description here

Upvotes: 1

Related Questions