Как реализовать множественный выбор на blazor при поиске текста имени сервера?

Я работаю на стороне сервера blazor. Я столкнулся с проблемой, я не могу применить .multiselect(); множественный выбор на основе веб-API?

Мне нужен множественный выбор как отображение текста server1, server2 при поиске.

при выборе в первый раз, затем сервер1 и во второй раз выберите сервер2, затем server1,server2

что я пытаюсь, как показано ниже:

1 - создать модельные серверы

public class ServerNames
    {
        [Key]
        public int ServerID { get; set; }
        [Required(ErrorMessage = "Server name is required")]
        public string Server_Name{ get; set; }
    }

2 - Реализовать сервис

List<ServerNames> GetSimilarServers(string searchText);

    
public List<ServerNames> GetSimilarServers(string searchText)
        {
            var serverNames = _context.ServerNames.Where(p => p.Server_Name.Contains(searchText)).ToList();

            return serverNames;
        }

3 - вызов службы на веб-API контроллера

[HttpGet]
            [Route("/api/ServerNames/GetSimilarServers/{searchText}")]
            public JsonResult GetSimilarServers(string searchText)
            {
                var serversName =  _IserverNamesService.GetSimilarServers(searchText);
    
                return new JsonResult(serversName);
            }

4 - в компоненте server.razor я вызываю веб-API, делаю поисковый фильтр

@code 
{
private List<ServerNames> SimilarServers{ get; set; }
public  async Task<ServerNames> DisplayListServer(string SearchText)
    {
       
        var serversLists = await GetSimilarServers(SearchText);

        SimilarServers = serversLists.ToList();
       
    }
public async Task<IEnumerable<ServerNames>> GetSimilarServers(string searchText)
    {
        HttpClient httpClient = new HttpClient();
        var response = await httpClient.GetAsync(config["API_URL"] + "ServerNames/GetSimilarServers/" + searchText + "");
        if (response.IsSuccessStatusCode)
        {
            var result = await JsonSerializer.DeserializeAsync<ServerNames[]>(await response.Content.ReadAsStreamAsync(), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
            return result;
        }
        else
        {
            return null; //handle the response that was not successful here.
        }
    }
}

что я пытаюсь

<select class = "form-select">
                                        @if (serversname.Any())
                                        {
                                            
                                        
                                        <option value = "0">--Select--</option>
                                        @foreach (var serv in SimilarServers)
                                        {
                                            <option value = "@serv.serverID">
                                                @serv.server_Name
                                            </option>
                                        }
                                        }

                                    </select>

Как заставить select принимать множественный текст выбора как server1, server2 и т. д.

Обновленный пост

Мне нужно выпадающее меню принять множественный выбор с флажком поэтому, если я отмечу сервер 1 и сервер 2, тогда сервер1, сервер2

см. изображение ниже

Какова длина списка серверов?

MrC aka Shaun Curtis 15.04.2023 08:32

ровно 200 серверов - это точное количество серверов

ahmed abdelaziz 15.04.2023 16:27

если что-то не ясно, дайте мне сейчас, пожалуйста

ahmed abdelaziz 15.04.2023 16:59

Почему некоторые части кода отсутствуют, например атрибут multiple в элементе select? Не совсем понятно, просите ли вы полное решение или просто просите помощи в отношении определенной части кода.

ViRuSTriNiTy 17.04.2023 10:42

мое решение, которое мне нужно, это раскрывающийся список с множественным выбором с флажком, поэтому, если я отмечу сервер1 и сервер 2, затем сервер1, сервер2

ahmed abdelaziz 17.04.2023 10:58

дайте мне знать, если мой результат мне не нужен

ahmed abdelaziz 17.04.2023 11:04

Что произойдет, если из ваших результатов поиска будет исключен сервер, который уже выбрал пользователь? Как вы справляетесь с этим? Создать работающий UX не так просто, как кажется на первый взгляд. Для этого решения вам почти наверняка понадобятся два элемента управления: список выбранных элементов и список элементов, которые вы можете выбрать или отменить выбор.

MrC aka Shaun Curtis 17.04.2023 23:22
Как конвертировать HTML в PDF с помощью jsPDF
Как конвертировать HTML в PDF с помощью jsPDF
В этой статье мы рассмотрим, как конвертировать HTML в PDF с помощью jsPDF. Здесь мы узнаем, как конвертировать HTML в PDF с помощью javascript.
2
7
124
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

С 200 элементами для выбора вам не нужно беспокоиться о получении отфильтрованного списка при каждом нажатии клавиши. Получите лот и используйте список данных.

Вот мой составной элемент управления, который близок к тому, что, я думаю, вы хотите:

@inject CountryPresenter _presenter
@using System.Linq.Expressions;
@using System.Diagnostics.CodeAnalysis;

<div class = "col-12 col col-lg-4 mb-3">
    <label class = "form-labelsm small">@this.Label</label>
    <div class = "input-group">
        <input type = "text"
               list = "@listId"
               @bind:get=_currentValue
               @bind:set=this.SetValue
               placeholder = "@this.PlaceholderText"
               @attributes=this.AdditionalAttributes />
        <button class = "btn btn-success" disabled = "@_isNotCurrentValue" @onclick=AddCurrentValue>Add</button>
    </div>
</div>
<datalist id = "@listId">
    @foreach (var option in OptionItems)
    {
        <option>@option</option>
    }

</datalist>

@foreach (var item in _selectedItems)
{
    <div class = "m-1 p-1">
        <span class = "badge bg-danger" style = "cursor:pointer;" @onclick = "() => this.DeleteItem(item)">Remove</span>
        <span class = "ms-4">@item</span>
    </div>
}

@code {
    [CascadingParameter] private EditContext? _editContext { get; set; }

    [Parameter] public string[]? Value { get; set; }
    [Parameter] public EventCallback<string[]?> ValueChanged { get; set; }
    [Parameter] public Expression<Func<string[]>>? ValueExpression { get; set; }

    [Parameter, EditorRequired] public IEnumerable<string> OptionItems { get; set; } = default!;

    [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
    [Parameter, EditorRequired] public string Label { get; set; } = "No Label";
    [Parameter] public string PlaceholderText { get; set; } = "Select a Value";

    private List<string> _selectedItems = new();
    private readonly string listId = Guid.NewGuid().ToString();
    private string? _currentValue;
    private bool _isNotCurrentValue => _currentValue is null;

    public override Task SetParametersAsync(ParameterView parameters)
    {
        parameters.SetParameterProperties(this);
        _selectedItems = new();

        if (this.Value is not null)
            _selectedItems = this.Value.ToList();

        return base.SetParametersAsync(parameters);
    }
    private void SetValue(string value)
    => _currentValue = value;

    private void DeleteItem(string value)
    {
        if (_selectedItems.Any(item => item.Equals(value)))
        {
            _selectedItems.Remove(value);
            this.NotifyEditContext();
            ValueChanged.InvokeAsync(_selectedItems.ToArray());
        }
    }

    private void AddCurrentValue()
    {
        if (_currentValue is not null && !_selectedItems.Any(item => item.Equals(_currentValue)))
        {
            _selectedItems.Add(_currentValue);
            _currentValue = null;
            this.NotifyEditContext();
            ValueChanged.InvokeAsync(_selectedItems.ToArray());
        }
    }

    private void NotifyEditContext()
    {
        if (ValueExpression is not null && _editContext is not null)
        {
            var fi = FieldIdentifier.Create(ValueExpression);
            _editContext?.NotifyFieldChanged(fi);
        }
    }
}

Демонстрационная страница

@page "/"
@inject CountryPresenter _countryPresenter
<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

<div class = "mb-3">Welcome to your new app.</div>


<MultiSelectControl class = "form-control"
                    Label = "Select Countries"
                    @bind-Value=_countryPresenter.SelectedCountries
                    OptionItems=_countryPresenter.CountryList />

@*Display the data*@
<div class = "bg-dark text-white p-2 mt-5">
    @if (_countryPresenter.SelectedCountries is not null)
    {
        @foreach (var item in _countryPresenter.SelectedCountries)
        {
            <pre>@item</pre>
        }
    }
</div>

@code {
    protected async override Task OnInitializedAsync()
        => await _countryPresenter.LoadingTask;
}

Служба представления, которая управляет данными.

public class CountryPresenter
{
    private CountryDataProvider _countryProvider;

    public string[]? SelectedCountries { get; set; }
    public IEnumerable<string> CountryList = Enumerable.Empty<string>();

    public Task LoadingTask { get; private set; } = Task.CompletedTask;

    public CountryPresenter(CountryDataProvider countryProvider)
    {
        _countryProvider = countryProvider;
        this.LoadingTask = this.LoadCountriesAsync();
    }

    private async Task LoadCountriesAsync()
        => this.CountryList = await _countryProvider.GetCountyListAsync();
}

И поставщик данных о стране для наших данных.

public class CountryDataProvider
{
    public async ValueTask<IEnumerable<string>> GetCountyListAsync()
    {
        //Dummy a async DB Call
        await Task.Yield();

        return CountryArray.AsEnumerable();
    }

    public static string[] CountryArray = new string[]
    {
            "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda",
            "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas",  "Bahrain", "Bangladesh",
            "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina",
            "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",  "Brunei Darussalam", "Bulgaria", "Burkina Faso",
            "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile",
            "China", "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", "Congo, the Democratic Republic of the",
            "Cook Islands", "Costa Rica", "Cote D'Ivoire", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti",
            "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
            "Falkland Islands (Malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Territories",
            "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala",
            "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Heard Island and Mcdonald Islands", "Holy See (Vatican City State)", "Honduras",
            "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
            "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait",
            "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya", "Liechtenstein",
            "Lithuania", "Luxembourg", "Macao", "Macedonia, the Former Yugoslav Republic of", "Madagascar", "Malawi", "Malaysia", "Maldives",
            "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of",
            "Moldova, Republic of", "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal",
            "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island",
            "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Palestinian Territory, Occupied", "Panama", "Papua New Guinea",
            "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
            "Rwanda", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines",
            "Samoa",  "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia and Montenegro", "Seychelles", "Sierra Leone",
            "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands",
            "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
            "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste", "Togo", "Tokelau",
            "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine",
            "United Arab Emirates", "United Kingdom", "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu",
            "Venezuela", "Viet Nam", "Virgin Islands, British",   "Virgin Islands, US", "Wallis and Futuna", "Western Sahara",
            "Yemen", "Zambia", "Zimbabwe",
    };
}

Регистрация службы:

builder.Services.AddScoped<CountryDataProvider>();
builder.Services.AddTransient<CountryPresenter>();

Другие вопросы по теме