Как создать динамический список с чекбоксами и метками в Blazor, чтобы избежать ошибок при выборе?

Рейтинг: 0Ответов: 1Опубликовано: 19.04.2023

Я пытаюсь создать динамический список в Blazor, где каждый элемент списка содержит чекбокс и соответствующую метку. Я хочу, чтобы при нажатии на метку соответствующий чекбокс активировался без ошибок. Вот код, который я написала

@foreach (var item in Items)
{
    <div class="listSelector">
        @if (RowTemplate is not null)
        {
            <input type="checkbox" id="checkbox_@intList" name="item_@intList" value="@intList" />
            <label for="checkbox_@intList">@RowTemplate(item)</label>
        }
    </div>

    intList++;
}

<style>
    .listSelector {
        display: flex;
        flex-direction: column;
    }
</style>

@code
{
    public int intList { get; set; } = 0;
}

Проблема: При нажатии на метку иногда активируется не тот чекбокс, который должен. Я попыталась сделать каждый пункт уникальным с помощью переменной intList, но проблема остается.

Вопрос: Как правильно создать динамический список с чекбоксами и метками, чтобы они работали корректно и каждый элемент списка был уникальным? Как можно улучшить мой код, чтобы избежать этой проблемы с выбором?

Ответы

▲ 0Принят

Для решения вашей проблемы с динамическим списком чекбоксов и меток в Blazor рекомендуется использовать директиву @bind, чтобы связать состояние чекбокса с моделью данных. Что позволит автоматически обновлять состояние модели при взаимодействии с пользовательским интерфейсом.

Ниже приведен пример, который демонстрирует использование @bind для связи состояния чекбоксов с моделью CheckboxItem. В этом примере также добавлена функция OnSubmit, и на скриншоте выбранные эллементы

введите сюда описание изображения

@page "/checkbox-list"

@foreach (var item in Items.Select((value, index) => new { value, index }))
{
    <div class="listSelector">
        <input type="checkbox" id="checkbox_@item.index" 
               @bind="@item.value.IsChecked" />
        <label for="checkbox_@item.index">@item.value.Name</label>
    </div>
}

<button @onclick="OnSubmit">Submit</button>

<style>
    .listSelector {
        display: flex;
        flex-direction: column;
        margin-bottom: 8px; 
    }
</style>

@code {
    public List<CheckboxItem> Items { get; set; } = new List<CheckboxItem>
    {
        new CheckboxItem { Name = "Item 1", IsChecked = false },
        new CheckboxItem { Name = "Item 2", IsChecked = false },
        new CheckboxItem { Name = "Item 3", IsChecked = false }
    };

    private void OnSubmit()
    {
        var selectedItems = Items
                            .Where(item => item.IsChecked)
                            .Select(item => item.Name)
                            .ToList();
    }

    public class CheckboxItem
    {
        public string Name { get; set; }
        public bool IsChecked { get; set; }
    }
}

Переиспользование компонента с RenderFragment

Если вы хотите использовать этот функционал в разных частях вашего проекта, не дублируя код, можно создать компонент и использовать RenderFragment для передачи шаблона. Это позволяет гибко определять, как каждый элемент списка должен отображаться.

razorPage

@page "/example"

@using MyProjectNameSpace.Data

<CheckboxListComponent TItem="string" Items="@items" RowTemplate="RenderTemplate" />

@code {
    private List<CheckboxItem<string>> items = new List<CheckboxItem<string>>
    {
        new CheckboxItem<string> { Item = "Item 1", IsChecked = false },
        new CheckboxItem<string> { Item = "Item 2", IsChecked = false },
        new CheckboxItem<string> { Item = "Item 3", IsChecked = false }
    };

    private RenderFragment<string> RenderTemplate => (item) => @<span>@item</span>;
}

component CheckboxListComponent

@using MyProjectNameSpace.Data
@typeparam TItem

@foreach (var item in Items.Select((value, index) => new { value, index }))
{
    <div class="listSelector">
        <input type="checkbox" id="checkbox_@item.index" 
               @bind="@item.value.IsChecked" />
        <label for="checkbox_@item.index">
            @RowTemplate(item.value.Item)
        </label>
    </div>
}

<button @onclick="OnSubmit">Submit</button>

<style>
    .listSelector {
        display: flex;
        flex-direction: column;
        margin-bottom: 8px; 
    }
</style>

@code {
    [Parameter] public List<CheckboxItem<TItem>> Items { get; set; } 
    = new List<CheckboxItem<TItem>>();
    [Parameter] public RenderFragment<TItem> RowTemplate { get; set; }  
    // RenderFragment<TItem> как параметр

    private void OnSubmit()
    {
        var selectedItems = Items
                            .Where(item => item.IsChecked)
                            .Select(item => item.Item)
                            .ToList();
    }
}

Эти примеры показывают, как можно использовать Blazor для создания динамических списков с чекбоксами, обеспечивая правильную работу, также привела пример компонента, который мы переиспользуем в нашем проекте не дублируя каждый раз код html