Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor inline editing table and getting all component values on event

On a Blazor component, I have this table in which I'm trying to implement inline editing functionality. I've managed the visual bits, but when it comes to grabbing the new values from the changed row on button click, I have no clue how to proceed.

Each row on the table is based on this object:

public class InstanceData 
{
    public Guid Id { get; set; }
    public string DisplayName { get; set; }
    public string BaseAddress { get; set; }
    public int Port { get; set; }
    public string Version { get; set; }
    public string AdditionalInformation { get; set; }

    [JsonIgnore]
    public bool IsEditing { get; set; }
}

On my razor page, table is populated like following:

<table>
    @*<thead tbody blah blah>*@

    @foreach (var instance in serverInstances)
    {
        if (instance.IsEditing)
        {
            <tr>
                <th scope="row">@instance.GetShortenedIdentifier()</th>
                <td>
                    <input type="text" class="form-control" placeholder="Give the instance a name" value="@instance.DisplayName" />
                </td>
                <td>
                    <input type="text" class="form-control" placeholder="e.g. http://localhost (without port)" value="@instance.BaseAddress" />
                </td>
                <td>
                    <input type="number" class="form-control" placeholder="The port number server is running on" value="@instance.Port"
                            min="0" max="65535" />
                </td>
                <td>
                    <input type="text" class="form-control" placeholder="For information purposes and not required" value="@instance.Version" />
                </td>
                <td>
                    <input type="text" class="form-control" placeholder="Any other details to add (e.g. Feature environment mocks instance)" value="@instance.AdditionalInformation" />
                </td>
                <td>
                    <button type="button" class="btn btn-link" @onclick="() => EnableEditing(false, instance)">
                        <i class="fas fa-window-close" />
                    </button>
                    <button type="button" class="btn btn-link" @onclick="() => UpdateInstance(instance)">
                        <i class="fas fa-check-square" />
                    </button>
                </td>
            </tr>
        }
        else
        {
            <tr>
                <th scope="row">@instance.GetShortenedIdentifier()</th>
                <td>@instance.DisplayName</td>
                <td>@instance.BaseAddress</td>
                <td>@instance.Port</td>
                <td>@instance.Version</td>
                <td>@instance.AdditionalInformation</td>
                <td>
                    <button type="button" class="btn btn-link" @onclick="() => EnableEditing(true, instance)">
                        <i class="fas fa-pen" />
                    </button>
                </td>
            </tr>
        }
</table>



@code {
    private void EnableEditing(bool flag, InstanceData instanceData)
    {
        instanceData.IsEditing = flag;
    }

    private void UpdateInstance(InstanceData instanceData)
    {
        EnableEditing(false, instanceData);

        //call the repository to update the instance here.
        //show toast after done.
    }
}

So, what I am trying to do is to get all those input element values to be passed into my method on @onclick="() => UpdateInstance(instance)" action. I've thought of assigning Id or fiddle with @ref but failed. What's the correct way to do this, or am I approaching this in a wrong way?

To visualise it, here's a little something with my awesome ms paint skills. blazor thingy

like image 867
Michael Wayne Avatar asked Mar 28 '20 20:03

Michael Wayne


1 Answers

You're setting the input values using the object values but not binding them.

<input type="text" class="form-control" placeholder="Give the instance a name" value="@instance.DisplayName" />

This will set the value of the input control but won't pass updates to anything.

You need to @bind the values to the property, e.g.

<input type="text" class="form-control" placeholder="Give the instance a name" @bind="@instance.DisplayName" />

This will update the underlying object's properties with any changes.

More: https://docs.microsoft.com/en-us/aspnet/core/blazor/data-binding?view=aspnetcore-3.1

like image 154
Quango Avatar answered Oct 03 '22 08:10

Quango