Megabit / Blazorise

Blazorise is a component library built on top of Blazor with support for CSS frameworks like Bootstrap, Tailwind, Bulma, AntDesign, and Material.
https://blazorise.com/
Other
3.26k stars 526 forks source link

Filter by DisplayTemplate #331

Closed Saeidasadi32 closed 4 years ago

Saeidasadi32 commented 4 years ago

when used DataGridSelectColumnis but DisplayTemplate is text , how do i filter by displaytemplate!

                            <DataGridSelectColumn TItem="Company" Field="@nameof( Company.CGroup )" Caption="گروه صنعت">
                                <DisplayTemplate>
                                    @{
                                        var cgroup = (context as Company)?.CGroup;
                                        @(companyGroups.Find(x => x.GID == cgroup).GName)
                                    }
                                </DisplayTemplate>
                            </DataGridSelectColumn>
stsrki commented 4 years ago

It seems this is not supported yet. I will look into it.

stsrki commented 4 years ago

Hi @Saeidasadi32

I spent last couple of days trying to figure it how to implement filtering on DisplayTemplate. And there is no easy way to do it without completely refactoring the data-grid. The main problem is in Blazor RenderFragment as I'm unable to get the right value when it's rendered.

So, unfortunately I will leave this task for the future when hopefully I will have more time to think it through.

In the meantime, as a workaround, you can have calculated properties in your models to have filters working.

public class MyModel
{
    public string Field1 { get; set; }

    public string Field2 { get; set; }

    public string SomeCustomValue => $"@hello: {Field1} {Field2}";
}
<DataGridColumn TItem="MyModel" Field="@nameof( MyModel.SomeCustomValue )" Caption="Custom field" Editable="false" />
rdnlsmith commented 4 years ago

Would it be any easier/any harder/at all sensible to accept a custom filter delegate on a given DataGridColumn?

For an example, suppose you have an Order data type with a CustomerId field, and you have another Customer data type that has CustomerId and CustomerName. Building from your calculated property suggestion, you might make a class like

public class DataGridOrder : Order
{
    public string CustomerName => GetCustomerNameFunc?.Invoke(CustomerId);
    public Func<int, string> GetCustomerNameFunc { get; set; }
}

In your page, you would have something like

private List<Customer> customers;
private List<DataGridOrder> orders;

protected override async Task OnInitializedAsync()
{
    customers = await _service.GetCustomersAsync();
    orders = await _service.GetOrdersAsync();
    foreach (var order in orders)
    {
        order.GetCustomerNameFunc = GetCustomerName;
    }
}

private string GetCustomerName(int customerId)
{
    return customers.FirstOrDefault(c => c.CustomerId == customerId)?.CustomerName ?? "";
}

Now already, you can create a datagrid with two columns:

<DataGrid ... >
    <DataGridSelectColumn ... Field="@nameof(DataGridOrder.CustomerId)" Editable="true">
        <EditTemplate>
            <SelectEdit ... />
        </EditTemplate>
    </DataGridSelectColumn>
    <DataGridColumn ... Field="@nameof(DataGridOrder.CustomerName)" Editable="false"/>
</DataGrid>

This allows you to see and filter on the CustomerName as a separate column, and present a single SelectEdit for the CustomerId field in the edit view. However, if we could specify a custom filter delegate, we could reduce it to just one column:

<DataGrid ... >
    <DataGridSelectColumn ... Field="@nameof(DataGridOrder.CustomerId)"
                              Editable="true"
                              Filter="@((searchValue) => { return (context as DataGridOrder).CustomerName.Contains(searchValue); })">
        <EditTemplate>
            <SelectEdit ... />
        </EditTemplate>
    </DataGridSelectColumn>
</DataGrid>

Another possibility would be to make it so you can have columns appear in the edit view that don't appear in the normal view—that way, you can display/filter on only the CustomerName field but still see the CustomerId field when editing. However, the custom filter delegate would also allow you to calculate a filter value inline, without needing to create a DataGridOrder object with extra properties.

stsrki commented 4 years ago

Not sure if I understood it, but if you want to filter by multiple columns that will be possible in the next release. It's done with this PR #716

PS. This ticket is already done and closed, so if above solution is not good enough please open new ticket. tnx

rdnlsmith commented 4 years ago

I don’t think that’s exactly what I was trying to suggest. It looks like #716 allows you to have a single search value look across multiple columns? Whereas, I was interested in overriding the filter comparison for a single column. So, all the individual column filters would still work as normal, but I could override the filter for an ID column so that it would actually compare the search text with a calculated display value instead of the ID.

The real goal for me was to have one editable column which stores an ID but displays some other text, which could be filtered.

With #716, is it possible to access the values of each individual column’s filter box in the custom handler? If so, I could probably make that do what I am looking for.

Thanks for all your work!