我已经搜索过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"> </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);
}
}
我遵循了一些用于实现事件的常规示例,但我发现并没有一个能真正解决问题。
答案 0 :(得分:1)
此代码段有效。尝试一下...运行代码,然后开始输入单词 Item 3 。键入时,您会看到子组件和父组件同时显示的类型文本。当您完成输入项目3时,您会注意到文本项目3 显示在组合框中。从组合框中选择一个项目,该项目将显示在父级的输入框中。
<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; }
}
@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"> </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"