读取子组件值的最佳实践

时间:2020-01-21 20:20:26

标签: c# razor blazor

我创建了一个Razor组件,它是一个简单的输入类型,如下所示:

@using ComponentPackage.Common

<input type="text" @bind="InputValue" />

@code {
    [Parameter]
    public EventCallback<string> ValueChanged { get; set; }

    private string inputValue;
    public string InputValue
    {
        get => inputValue;
        set
        {
            inputValue = value;
            ValueChanged.InvokeAsync(value);
        }
    }
}

然后,在Razor页面上像这样设置子组件:

@page "/newpage"
@using ComponentPackage.Common

<ComponentPackage.Components.TextBox ValueChanged="OnValueChanged"></ComponentPackage.Components.TextBox>
<input type="button" @onclick="TestContent" value="Test" />
<br /><br />
You have entered : @ReturnValue

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

    private void TestContent()
    {
        // Here I want to get the value from the component
    }

    public void OnValueChanged(string returnValue)
    {
        ReturnValue = returnValue;
    }
}

在页面中,我将组件事件连接到OnValueChanged。一旦我离开该字段,ReturnValue属性就是更新。

问题是:单击页面上的按钮时,如何读取文本框中的值?换句话说,我不希望在离开文本框时设置ReturnValue。我尝试对页面上的属性使用bind-InputValue,但是它始终为null。

3 个答案:

答案 0 :(得分:1)

我认为这是您所需要的:组件中的双向数据绑定 以下是您想要的完整且有效的代码... 复制,粘贴并运行...

以下示例显示了如何在父组件及其子组件之间执行双向数据绑定。在这两个组件的每一个中,都有一个文本框控件。在父组件的文本框中键入文本时,子组件的文本框中的文本会更改以反映父组件中所做的更改,反之亦然...

ChildComponent.razor

    <div style="border:solid 1px red">
        <h2>Child Component</h2>
        <input type="text" @bind="Text" @bind:event="oninput" />
    </div>

@code {
    private string text { get; set; }

    [Parameter]
    public string Text
    {
        get { return text; }
        set
        {
            if (text != value) {
                text = value;
                if (TextChanged.HasDelegate)
                {
                    TextChanged.InvokeAsync(value);
                }
            }
        }
    }

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

ParentComponent.razor

@page "/ParentComponent"

<h1>Parent Component</h1>

<input type="text" @bind="Text" @bind:event="oninput" />
<p></p>

<ChildComponent @bind-Text="Text" />


@code {
    [Parameter]
    public string Text { get; set; } = "Hello Blazor";
}

将此内容添加到Shared / NavMenu.razor,并测试代码:

<li class="nav-item px-3">
            <NavLink class="nav-link" href="ParentComponent">
                <span class="oi oi-plus" aria-hidden="true"></span> ParentComponent
            </NavLink>
        </li>

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

答案 1 :(得分:1)

这是我的解决方案,希望对您有帮助

我将StateDropdown作为子组件

@inject HttpClient httpClient

@if (States != null)
{
<select id="SearchStateId" name="stateId" @onchange="@StateChange" class="form-control1">
    <option>@InitialText</option>
    @foreach (var state in States)
    {
        <option value="@state.Name">@state.Name</option>
    }
</select>
}

@code {
[Parameter] public string SelectedText { get; set; } = string.Empty;
[Parameter] public string InitialText { get; set; } = "Select State";
[Parameter] public EventCallback<string> SelectedTextChanged { get; set; }
private KeyValue[] States;
protected override async Task OnInitializedAsync()
{
    States = await httpClient.GetJsonAsync<KeyValue[]>("/sample-data/State.json");
}

private async Task StateChange(ChangeEventArgs e)
{
    //Console.WriteLine("It is definitely: " + e.Value.ToString());
    await SelectedTextChanged.InvokeAsync(e.Value.ToString());
}

public class KeyValue
{
    public int Id { get; set; }

    public string Name { get; set; }
}
}

然后在我的页面中,我添加了State下拉列表,

<StateDropdown @bind-SelectedText="@searchFilter.State" InitialText="All India"></StateDropdown>
<input type="button" id="btnSearch" class="btn-default form-control1" @onclick="@SearchAdertisements" value="Search" />


@code {
 private SearchFilter searchFilter = new SearchFilter();
 public class SearchFilter
{
    public string State { get; set; } = string.Empty;

    public string Category { get; set; } = string.Empty;
}

private async Task SearchAdertisements()
{
    Console.WriteLine(searchFilter.State);
}

您可以read以获得更多详细信息。

答案 2 :(得分:0)

我试图将其更改为:..因此它正在使用bind-InputValue而不是绑定到事件。但这给了我以下错误:类型为'ComponentPackage.Components.TextBox'的对象具有与名称'InputValue'相匹配的属性,但没有应用[ParameterAttribute]或[CascadingParameterAttribute] –

如果在像这样的父组件中使用TextBox组件:

<TextBox @bind-InputValue="ReturnValue" />

您将TextBox组件绑定到您在父组件中定义的变量,如下所示:

private string ReturnValue {get; set;}

通过触发EventCallback'delegate',将使用TextBox中的值更新ReturnValue属性。

InputValue(上面使用过:@ bind-InputValue =“ ReturnValue”)应定义为公共参数属性,如下所示:

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

您还需要在子组件(名为TextBox)中为EventCallback'delegate'定义一个公共参数属性,如下所示:

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

如您所见,我们创建了一个由属性和EventCallback组成的对

如果您的属性名为InputValue,则您的EventCallback应该命名为InputValueChanged。

如果您的属性命名为Value,那么您的EventCallback应该命名为ValueChanged。

如果您的属性命名为Text,那么您的EventCallback应该命名为TextChanged。

它们总是成对出现。

现在回到我的第一个答案,学习代码,运行它进行测试,尽情享受,别忘了投票给我答案...