如何在SELECT组件中的Blazor中实现双向绑定?

时间:2020-02-14 01:02:50

标签: c# html-select blazor blazor-server-side

我已经搜索过SO,对此问题有一些疑问和答案,但没有一个能解决这个特定问题。

我正在尝试编写一个使用<select...> Blazor组件,以更新从父级传入的变量。

我想单击下拉菜单(选择/选项),选择一个选项,然后让其自动更新父项中的变量。

如果不使用组件,我可以使其正常工作。但是,使它在组件中运行的唯一方法是,如果我还在组件中使用一个按钮(请参阅组件代码中的按钮)。但是最终将有多个组件由同一个父组件调用。每个组件都有一个单独的按钮是不切实际的。因此按钮必须消失。

@bind 使用“ onchange”参数进行选择,因此甚至无法编译。

我已经尝试过 CascadingValue / CascadingParam ,但这也不会更新父值(除非我使用按钮...)

这是父母:

@page "/test"
@page "/test/{param}"

@namespace ComponentTest.Pages

@using System.Web
@using ComponentTest.Pages

<h3>Test Page</h3>

<div class="border col-3">
    <h4>Parent</h4>
    <hr />
    <label for="parentValue">Parent Value</label>
    <input id="parentValue" @bind="@param"/>
</div>
<div class="col-3">&nbsp</div>
<div class="border col-3">
    <h4>Component Select</h4>
    <hr />
    <SelectComponent @bind-Item="@param"/>
</div>

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

这是组件:

@using System.Collections.Generic
@using System.Web

<div class="form-group">
    <p>Component Value = @Item</p>
    <label for="Site" class="font-weight-bold form-check-label">List</label>
    @if (list == null)
    {
        <input id="Item" class="form-control-sm" @bind="@Item" />
    }
    else
    {
        <select id="Item" class="form-control-sm" @bind="@Item">
            @foreach (var l in list)
            {
                @if (Item != null && String.Equals(l, Item, StringComparison.OrdinalIgnoreCase))
                {
                    <option selected value="@l">@l</option>
                }
                else
                {
                    <option value="@l">@l</option>
                }
            }
        </select>
    }
</div>
<button @onclick="UpdateParentsItem" class="btn btn-primary">Update Parent</button>
@code {
    public IEnumerable<string> list = new List<string>()
{
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4",
        "Item 5"
    };

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

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

    private async Task UpdateParentsItem()
    {
        await ItemChanged.InvokeAsync(Item);
    }
}

我遵循了一些用于实现事件的常规示例,但我发现并没有一个能真正解决问题。

3 个答案:

答案 0 :(得分:1)

此代码段有效。尝试一下...运行代码,然后开始输入单词 Item 3 。键入时,您会看到子组件和父组件同时显示的类型文本。当您完成输入项目3时,您会注意到文本项目3 显示在组合框中。从组合框中选择一个项目,该项目将显示在父级的输入框中。

SelectComponent.razor

    <div style="border:solid 1px red">
     <select id="Item" class="form-control-sm" @bind="@Item">
        @foreach (var l in list)
        {
            @if (Item != null && String.Equals(l, Item, 
             StringComparison.OrdinalIgnoreCase))
            {
                <option selected value="@l">@l</option>
            }
            else
            {
                <option value="@l">@l</option>
            }
        }
    </select>

 </div>
 <p>@Item</p>

 @code {
  public IEnumerable<string> list = new List<string>()
 {
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5"
 };


 private string item { get; set; } 

 [Parameter]
 public string Item
 {
    get { return item; }
    set
    {
        if (item != value)
        {
            item = value;
            if (ItemChanged.HasDelegate)
            {
                ItemChanged.InvokeAsync(value);
            }
        }
    }
  }

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

Test.razor

@page "/test"

<div>

<label for="parentValue">Parent Value</label>

<input type="text" id="parentValue" @bind="@Param" 
     @bind:event="oninput" />

<p>@Param</p>
</div>

<div>

<SelectComponent @bind-Item="@Param"/>
</div>

@code {
  [Parameter]
public string Param { get; set; } = string.Empty;

}

祝你好运...如果不清楚,请随时询问...

答案 1 :(得分:1)

我将答案归功于@enet,但这是我的完整解决方案,其中包括他的(她的?)位,并进行了额外的验证检查:

Test.razor(父级)

val tmp_df2 = tmp_df1.withColumn("col_one", when($"col_two" === "good", "bad").otherwise($"col_one"))

SelectComponent.razor

@page "/test"
@page "/test/{param}"

<h3>Select Component Test</h3>

<div class="border col-2">
    <h4>Parent</h4>
    <hr />
    <div class="form-group">
        <label for="parentValue">Parent Value</label>
        <input id="parentValue" type="text" class="form-control" @bind="@param" />
    </div>
</div>
<div class="col-3">&nbsp</div>
<div class="border col-2">
    <h4>Component</h4>
    <hr />
    <SelectComponent @bind-Item="@param" />
</div>
<hr />
<ul>Links
    <li><a href="/test/item 1">item 1</a></li>
    <li><a href="/test/ITEM 2">ITEM 2</a></li>
    <li><a href="/test/iTeM 3">iTeM 3</a></li>
    <li><a href="/test/ItEm 4">ItEm 4</a></li>
    <li><a href="/test/item 99">item 99</a></li>
</ul>
@code
{
    [Parameter]
    public string param { get; set; }
}

我将使用它作为几个基于Entity Framework的表单验证下拉菜单的模板。

答案 2 :(得分:0)

这 2 个示例给出了这个 js 错误:未捕获(承诺)DOMException:无法在 'Element' 上执行 'setAttribute':'@bind' 不是有效的属性名称。 导致错误:@bind="@Item"