通过按下按钮更改 Blazor 应用程序中的 HTML 元素?

Change the HTML element in a Blazor application by pressing a button?

我想问一下是否可以通过按下按钮来更改 Blazor 应用程序中 HTML 元素的类型。 例如,我将普通文本转换为文本输入字段。

我有一个 table,其中第一列有一个按钮用于 table 中的每个条目。 我的目标是当您按下按钮时,字段会及时变成输入字段,这样您就可以编辑值了。

这只是一个快速的照片编辑,但这是我想象的样子。

这里有一个基本组件和演示页面,用于演示如何执行此操作。有一个组件和一个演示页面。

@page "/"
<div>
    <button class="btn btn-dark" disabled="@isEdit" @onclick="GoEdit">Edit</button>
    @if (this.isEdit)
    {
        @EditControl
    }
    else
    {
        @ViewControl
    }
</div>

@code {

    [Parameter] public RenderFragment ViewControl { get; set; }
    [Parameter] public RenderFragment EditControl { get; set; }

    protected string disabled => isEdit ? "disabled": "";
    protected bool isEdit { get; set; }
    private void GoEdit(MouseEventArgs e)
        => isEdit = !isEdit;
}

还有一个演示页面:

@page "/Demo"
<h3>EditorTest</h3>
<CascadingValue Value="model">
    <EditForm EditContext="editContext">
        <EditFormState @ref="editFormState" EditStateChanged="EditStateChanged"></EditFormState>
        <div>
            <SwitchedEditorComponent>
                <EditControl>
                    Email: <InputText @bind-Value="model.Email" placeholder="Enter your Email Address"></InputText>
                </EditControl>
                <ViewControl>
                    Email: <InputText @bind-Value="model.Email" disabled></InputText>
                </ViewControl>
            </SwitchedEditorComponent>
        </div>
    </EditForm>
</CascadingValue>


@code {

    private dataModel model { get; set; } = new dataModel();
    private EditFormState editFormState;
    private EditContext editContext;

    protected override Task OnInitializedAsync()
    {
        this.editContext = new EditContext(model);
        return base.OnInitializedAsync();
    }

    private void EditStateChanged(bool editState)
    {
        StateHasChanged();
    }

    public class dataModel
    {
        public string Email { get; set; }
    }
}

您可以添加一个索引数组来存储每个公司的编辑状态值。然后,该按钮将切换该值,如果为真,该单元格将显示输入而不是普通文本,您可以在其中编辑公司名称,该值将保存到列表或 class.

foreach 中添加 .Select((value, i) => new { i, value }) 允许获得对此功能很重要的索引信息。

@page "/companies"

<h1>Companies</h1>

<table class="table table-bordered table-sm">
    <thead>
        <tr>
            <th scope="col">#</th>
            <th scope="col">Companies</th>
        </tr>
    </thead>

    <tbody>

        @foreach (var company in Companies.Select((value, i) => new { i, value }))
        {
            var value = company.value;
            var index = company.i;
            <tr>
                <td><button type="button" class="btn btn-primary"
                            @onclick="@(() => { Edits[index] = !Edits[index]; })">
                                @(Edits[index] ? "Back" : "Edit")</button></td>
                <td>
                    @if (Edits[index]) {
                        <input class="form-control" type="text"
                               style="background-color:lightyellow;"
                               value="@value"
                               @oninput="@(e => {Companies[index] = e.Value.ToString();})"/>
                    } 
                    else {
                        @value
                    }
                </td>
            </tr>
        }

    </tbody>
</table>

<ul>
    @*Check realtime changes to Company names when you edit them*@
    @foreach (var value in Companies)
    {
        <li>@value</li>
    }

</ul>

@code {
    public List<String> Companies;

    // for storing edit status of each company
    // this array has to be same length as your company list
    public bool[] Edits;

    protected override void OnInitialized() {
        Companies = new List<String> {
             "Acme Corporation",
             "Globex Corporation",
             "Soylent Corp",
             "Initech",
             "Umbrella Corporation"
             };

        Edits = new bool[Companies.Count()];
    }
}

编辑:

您还可以添加另一个 属性 与公司名称(如位置)一起编辑。这样你就可以使用 class 而不是 string.

@* CompanyPage.razor *@
@page "/company"

<h3>Companies</h3>

<table class="table table-bordered table-sm">
    <thead>
        <tr>
            <th scope="col">#</th>
            <th scope="col">Company</th>
            <th scope="col">Location</th>
        </tr>
    </thead>

    <tbody>

        @foreach (var company in Companies.Select((value, i) => new { i, value }))
        {
            var value = company.value;
            var index = company.i;
            <tr>
                <td>
                    <button type="button" class="btn btn-primary"
                            @onclick="@(() => { Edits[index] = !Edits[index]; })">
                        @(Edits[index] ? "Back" : "Edit")
                    </button>
                </td>
                <td>
                    @if (Edits[index])
                    {
                        <input class="form-control" type="text"
                               style="background-color:lightyellow;"
                               value="@value.Name"
                               @oninput="@(e => {Companies[index].Name = e.Value.ToString();})" />
                    }
                    else
                    {
                        @value.Name
                    }
                </td>
                <td>
                    @if (Edits[index])
                    {
                        <input class="form-control" type="text"
                               style="background-color:lightyellow;"
                               value="@value.Location"
                               @oninput="@(e => {Companies[index].Location = e.Value.ToString();})" />
                    }
                    else
                    {
                        @value.Location
                    }
                </td>
            </tr>
        }

    </tbody>
</table>

<ul>
    @*Check realtime changes to Company names when you edit them*@
    @foreach (var value in Companies)
    {
        <li>@value.Name: @value.Location</li>
    }

</ul>

@code {
    public List<Company> Companies;

    // for storing edit status of each company
    // this array has to be same length as your company list
    public bool[] Edits;

    protected override void OnInitialized()
    {
        Companies = new List<Company>
    {
             new Company("Globex Corporation", "Germany"),
             new Company("Soylent Corp", "Switzerland"),
             new Company("Umbrella Corporation", "Netherlands")
        };

        Edits = new bool[Companies.Count()];
    }

    public class Company
    {
        public Company(string name, string location)
        {
            Name = name;
            Location = location;
        }
        public string Name { get; set; }
        public string Location { get; set; }
    }
}