Search code examples
c#razorblazor

Is it possible to use one parameter for blazor two-way binding and an expression of the same property


I'm creating a component to simplify the TextAreas in my application. I've setup the two-way binding and validation (using FluentValidation). My problem is that for each usage of the component, i'm calling the same property twice. I was wondering if there was a way to only reference the property once, while keeping the two-way binding and validation reference. Any other improvements or guidance on how I could get the <InputTextArea> control working in this scenario would also be great.

Usage of my component:

<FormTextArea @bind-Value="User.FirstName" ValidationFor="() => User.FirstName" />

This is my FormTextArea.razor component:

@using System.Linq.Expressions;

<div class="col-12">
    <label class="form-label" for="@ID">@DisplayLabel</label>
    <textarea @bind="CurrentValue" id="@ID" class="@ValidationCssClass" rows="2" />
    <ValidationMessage For="ValidationFor" />
</div>


@code {

    [Parameter]
    public string Value { get; set; }

    [Parameter]
    public EventCallback<string> ValueChanged { get; set; }

    protected string CurrentValue
    {
        get
        {
            return Value;
        }
        set
        {
            if (!EqualityComparer<string>.Default.Equals(value, Value))
            {
                IsModified = true;
                Value = value;
                ValueChanged.InvokeAsync(Value);
                EditContext.Validate();
                EditContext.NotifyValidationStateChanged();
                StateHasChanged();
            }
        }
    }

    [CascadingParameter]
    public EditContext EditContext { get; set; }

    [Parameter]
    public Expression<Func<string>> ValidationFor { get; set; }

    [Parameter]
    public string ID { get; set; } = Guid.NewGuid().ToString();

    [Parameter]
    public string Label { get; set; }

    string DisplayLabel => string.IsNullOrEmpty(Label) ? PropertyHelper.GetDisplayName(ValidationFor) : Label;

    // The <InputTextArea> Wasn't getting the correct validation class so had to do it manually
    bool IsModified { get; set; } = false;
    string ValidationCssClass => $"form-control {(IsModified ? "modified" : "")} {EditContext.FieldCssClass(ValidationFor)}";
}


Solution

  • You should be able to modify this:

        [Parameter] public Expression<Func<string>> ValidationFor { get; set; }
    

    to this:

        [Parameter] public Expression<Func<string>> ValueExpression { get; set; }
    

    And then the Razor compiler will then do the work for you.