プロパティ名とタイプを知らなくても、Blazorコンポーネントのジェネリックリストパラメータをフィルタリングする方法

レイ

以下は、入力時にリストをフィルタリングする検索入力を含む順序付けされていないリストです。すべてが完璧に機能します:

@page "/todolist"

<input @bind-value="SearchTerm" @bind-value:event="oninput" />

<span class="text-muted ml-5">
    Showing @FilteredToDos.Count out of @ToDoItems.Count
</span>

<h4 class="mt-4">To Do's</h4>
<ul>
    @foreach (var toDo in FilteredToDos)
    {
        <li>@toDo.Name</li>
    }
</ul>

@code {
    // Initialize SearchTerm to "" to prevent null's
    string SearchTerm { get; set; } = "";

    // Data
    class ToDoItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    List<ToDoItem> ToDoItems => new List<ToDoItem>
    {
        new ToDoItem {Id = 1, Name = "Garbage" },
        new ToDoItem {Id = 2, Name = "Dishes" },
        new ToDoItem {Id = 3, Name = "Wash clothes" },
        new ToDoItem {Id = 4, Name = "Water flowers" }
    };
    //filter
    List<ToDoItem> FilteredToDos => ToDoItems.Where(i => i.Name.ToLower().Contains(SearchTerm.ToLower())).ToList();
}

リストを独自のコンポーネント(TodoComponent)に分離しました。

@typeparam TItem

<input @bind-value="SearchTerm" @bind-value:event="oninput" />

<h4 class="mt-4">To Do's</h4>
<ul>
    @foreach (var toDo in Todos)
    {
        @UnorderedList(toDo)
    }
</ul>

@code {
    [Parameter]
    public List<TItem> Todos { get; set; }
    [Parameter]
    public RenderFragment<TItem> UnorderedList { get; set; }

    string SearchTerm { get; set; } = "";

    List<TItem> FilteredToDos => Todos.Where(i => i.Name.ToLower().Contains(SearchTerm.ToLower())).ToList();
}

私はここでblazorコンポーネントを呼んでいます:

@page "/todo"

    <TodoComponent Todos="@ToDoItems">
        <UnorderedList>
            <li>ID: @context.Id Name: @context.Name </li>
        </UnorderedList>
    </TodoComponent>

@code {
    private List<ToDoItem> ToDoItems => new List<ToDoItem>
        {
            new ToDoItem {Id = 1, Name = "Garbage" },
            new ToDoItem {Id = 2, Name = "Dishes" },
            new ToDoItem {Id = 3, Name = "Wash clothes" },
            new ToDoItem {Id = 4, Name = "Water flowers" }
        };

    public class ToDoItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

}

リストは正常に表示されますが、リストをフィルタリングできなくなりました。フィルター機能をコンポーネントの外に置きたくありません。コンポーネント内の名前またはIDに基づいてフィルタリングするための最良の方法は何でしょうか?リストの代わりに別のデータ構造を使用する方が良いでしょうか?

ピーターモリス

あなたのコンポーネントにパラメータプロパティを追加しますと呼ばれるGetFilterDataことがありますFunc<TItem, string>

次にGetFilterData、各アイテムを呼び出して、アイテムを含めるかどうかを決定できます。

<table>標準テンプレートBlazorアプリのFetchDataマークアップを次のように変更します。

    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            <MyList Items=@forecasts GetFilterableText=@(item => $"{item.Date} {item.Summary} {item.TemperatureC} {item.TemperatureF}" )>
                <tr>
                    <td>@context.Date.ToShortDateString()</td>
                    <td>@context.TemperatureC</td>
                    <td>@context.TemperatureF</td>
                    <td>@context.Summary</td>
                </tr>
            </MyList>
        </tbody>
    </table>

次に、次のコンポーネントをアプリに追加します

@typeparam TItem

<input @bind=Filter @bind:event="oninput" />
@foreach (TItem item in GetFilteredItems())
{
    if (ChildContent == null)
    {
        <li>@item?.ToString()</li>
    }
    else
    {
        @ChildContent(item);
    }
}

@code {
        [Parameter]
        public IEnumerable<TItem> Items { get; set; }

        [Parameter]
        public Func<TItem, string> GetFilterableText { get; set; }

        [Parameter]
        public RenderFragment<TItem> ChildContent { get; set; }

    private string Filter;
    private static readonly Func<TItem, string> DefaultGetFilterableText =
        item => (item?.ToString() ?? "");


    private IEnumerable<TItem> GetFilteredItems()
    {
        Func<TItem, string> filterFunc = GetFilterableText ?? DefaultGetFilterableText;
        IEnumerable<TItem> result = (Items ?? Array.Empty<TItem>());
        if (!string.IsNullOrEmpty(Filter))
        {
            result = result
                .Where(x =>
                    (GetFilterableText(x) ?? "")
                    .Contains(Filter, StringComparison.InvariantCultureIgnoreCase));
        }
        return result;
    }

}

これをニーズに適合させることができるはずです。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ