Blazor TwoWay Binding on custom Component

寵の児 提交于 2020-07-15 12:12:42

问题


I'm creating a blazor server side app and have problems to bind a value between two custom components.

I've looked through different example of how the bind or @bind is supposed to work but I cannot figure out what up to date information on this matter is.

Given a model class User:

public class User
    {
        [Mapping(ColumnName = "short_id")]
        public string ShortId { get; set; }

        public User()
        {

        }
    }

I want to build a form which displays all properties of this user and has them in an input so it can be edited and in the end saved to a database.

My Form (parent component) looks like this:

<div class="edit-user-form">
    <AnimatedUserInput TbText="@User.ShortId" Placeholder="MHTEE Id"/>
    <button class="btn btn-secondary" @onclick="Hide" style="{display:inline-block;}">Back</button>
    <button class="btn btn-primary" @onclick="SaveUser" style="{display:inline-block;}">Save</button>
</div>
@code {
    [Parameter] public vUser User { get; set; }

    [Parameter] public Action Hide { get; set; }

    bool _error = false;

    void SaveUser()
    {
        ValidateUserData();
    }

    void ValidateUserData()
    {
        _error = string.IsNullOrWhiteSpace(User.ShortId);
    }
}

Where AnimatedUserInput is a custom component that looks like this:

<div class="edit-area @FocusClass @WiggleClass">
    <input type="text" @bind="@TbText" />
    <span data-placeholder="@Placeholder"></span>
</div>
@code {
    [Parameter]
    public string TbText { get; set; }

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

Now in the Input textbox I correctly see the ShortId of the User object in my parent component.

However if I change the text in the input and click on the Save button which triggers the ValidateUserData method and allows me to look at the current User object I see that no changes have been done in the actual User.ShortId property but only on the input.

Is there any way to bind it so that changes in the input will automatically be applied to the binded property?

I have several of these properies which need to be shown in the form which is why I dont want to hook a custom OnChanged Event for each of those properties.


回答1:


Ok so for anyone stumbling upon this. I tried a bit more and found a solution. So to my custom input component AnimatedUserInput I added a EventCallback which I call everytime the value on the input is updated:

@code {

    [Parameter]
    public string TbText
    {
        get => _tbText;
        set
        {
            if (_tbText == value) return;

            _tbText = value;
            TbTextChanged.InvokeAsync(value);
        }
    }

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

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

    private string _tbText;
}

And the binding on my parent component looks like this:

<div class="edit-user-form">
    <AnimatedUserInput @bind-TbText="@User.ShortId" Placeholder="MHTEE Id"/>
    <AnimatedUserInput @bind-TbText="@User.FirstName" Placeholder="First name" />
    <AnimatedUserInput @bind-TbText="@User.LastName" Placeholder="Last name" />
    <AnimatedUserInput @bind-TbText="@User.UserName" Placeholder="Username" />
    <AnimatedUserInput @bind-TbText="@User.StaffType" Placeholder="Staff type" />
    <AnimatedUserInput @bind-TbText="@User.Token" Placeholder="Token" />
    <button class="btn btn-secondary" @onclick="Hide" style="{display:inline-block;}">Back</button>
    <button class="btn btn-primary" @onclick="SaveUser" style="{display:inline-block;}">Save</button>
</div>

@code {
    [Parameter] public vUser User { get; set; }
}

This way blazor can correctly bind the values together and updates them from both sides the way I would expect them to bind.



来源:https://stackoverflow.com/questions/58196797/blazor-twoway-binding-on-custom-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!