smithygreg
smithygreg

Reputation: 605

Blazor Two Way Binding Text Area inside component

I am trying to two-way bind a text area inside a child component in Blazor and I just can't figure it out.

Parent

@page "/test"

<h3>Parent Component</h3>
<input type="text" @bind="mydata" />

<TWBTextArea @bind-ChildData=@mydata></TWBTextArea>

@code {
    public string mydata = "test";
}

Child

<h4>Child Component</h4>

<textarea @bind=@ChildData></textarea>

@code {
    [Parameter] public string ChildData { get; set; }

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

When I update from the parent component, the child textarea updates, but when I update the child text area, the parent is not updated.

Additional note : If I change the value being passed from a string to an object with a string property and I pass that object to the Child Component, two way binding DOES work but only after an update to the parent component.

Upvotes: 10

Views: 19256

Answers (3)

Jbtatro
Jbtatro

Reputation: 123

The current version of Blazor seems to have what you need. <InputTextArea @bind-Value="@prospect.Notes" Style="width:800px;height:200px;word-wrap:normal;" /> seems to work!

Documentation: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.forms.inputtextarea?view=aspnetcore-8.0

Upvotes: 7

Protector one
Protector one

Reputation: 7261

I seem to have it working now by inheriting InputBase and binding to the CurrentValue property, but it was definitely something of an uphill battle.

@inherits InputBase<string>


<textarea class="@Class" @bind="CurrentValue"
    @attributes="AdditionalAttributes" />


@code
{
    [Parameter]
    public string Id { get; set; }

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

    protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)
    {
        result = value;
        validationErrorMessage = null;
        return true;
    }
}

Upvotes: 1

enet
enet

Reputation: 45586

Important: You should not bind to components' parameters as it may have side-effects on your app. Read this post by Steve Sanderson

Note that I define a local variable, named data, into which I assign the ChildData parameter property's value from the OnParametersSet method. That is done, as I've said before, in order to refrain from binding to a component's parameter.

Since we are creating a two-way data-binding, the value attribute of the textarea element is bound to the variable data. The flow of data is from the variable to the element. We also need to create an event handler, named here HandleOnChange, whose role is to update the local variable data, as well as to invoke the EventCallback 'delegate', passing the new value stored in the data variable. This value is gladly received in the parent component's mydata field, after which, a re-rendering occurs to reflect the new changes.

Note that I'm using the input event, instead of the change event, to make life easier and more interesting.

Child component

<h4>Child Component</h4>

<textarea @oninput="HandleOnChange">@data</textarea>

@code {

    private string data;

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

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

    private async Task HandleOnChange(ChangeEventArgs args)
    {
        data = args.Value.ToString();

        await ChildDataChanged.InvokeAsync(data);
    }

    protected override void OnParametersSet()
    {
        data = ChildData;

        base.OnParametersSet();
    }
}

Usage

@page "/test"

<h3>Parent Component</h3>
<input type="text" @bind="mydata" @bind:event="oninput" />

<ChildComponent @bind-ChildData="mydata" />

@code {
    private string mydata = "test";
}

Upvotes: 16

Related Questions