BlazorTable icon indicating copy to clipboard operation
BlazorTable copied to clipboard

[Bug] Expressions as Column Fields are too type limited

Open dedmen opened this issue 3 years ago • 1 comments

Describe the bug You cannot use methods or lambda expressions as a Field expression.

Example. Field="@(x => x.UserName)" works fine. Field="@(x => x.GetInfoEx().FirstName)" works fine.

Field="@(x => GetHasDiscordString(x.GetInfoEx().DiscordID))" Crash

Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpression1' to type 'System.Linq.Expressions.UnaryExpression'. at https://github.com/IvanJosipovic/BlazorTable/blob/master/src/BlazorTable/Utillities.cs#L169

Field="@(x => x.GetInfoEx().DiscordID.HasValue ? "✓" : "❎")" Crash

Unable to cast object of type 'System.Linq.Expressions.FullConditionalExpression' to type 'System.Linq.Expressions.UnaryExpression'.

I have to implement my display value as a class member public string HasDiscordIDString => DiscordID.HasValue ? "✓" : "❎"; to make this work. The first couple times I had to do this that was fine, but its starting to become really messy.

To Reproduce

@page "/Bug152"

<Table TableItem="TestData" Items="data" ShowSearchBar="true" ShowFooter="true">
    <Column TableItem="TestData" Title="Has entry?" Sortable="false" Filterable="true" SetFooterValue="Count"  Field="@(x => x.entry.HasValue ? "✓" : "❎")"  />
</Table>

@code
{
    private TestData[] data;

    protected override void OnInitialized()
    {
        data = new TestData[]
        {
            new TestData()
            {
                entry = 5
            },
           new TestData()
            {
                entry = 5
            }
        };
    }

    public class TestData
    {
        public long? entry;
    }
}

Expected behavior No Exception being thrown.

dedmen avatar Jan 16 '21 15:01 dedmen

Had a similar issue, our solution was to wrap the function call with a class that can return the result we want as a unary expression.

For example:

public class StringWrapper
{
  public string Value { get; private set; }
  public StringWrapper(string value)
  {
    Value = value;
  }
}

then use the field like: Field="@(new StringWrapper(GetHasDiscordString(x.GetInfoEx().DiscordID).Value)"

There's possibly a better way to do this, but it works for us. If the Field isn't a string, I think it'd still work if it was made generic, but I haven't tried that.

Benjathing avatar Nov 17 '22 04:11 Benjathing