Blazor - 传递参数给父组件

8
如何在子组件的onClick事件中传递多个参数给父组件?
子组件 Razor:
@foreach( var item in items)
{
  @foreach( var score in item.scores)
  {
    <span @onclick="ItemClicked(item.name, score.id)"> 
      @item.name 
    </span>
  }
}

父级 Razor

<Child ItemClicked = "@ItemClicked"/>

@code{
 private void ItemClicked(string name, int id)
    {
        Console.WriteLine(name);
        Console.WriteLine(id);
    }
}

尝试:项目已点击 - AliNajafZadeh
6个回答

9

在子元素中

<span @onclick = "() => ItemClicked(item.name, score.id)"> @item.name</span>

@code 
{
   [Parameter] public Action<string,int> ItemClicked { get; set; }
}

1
如何在父组件中处理它? - Ahmed Imam
1
你已经在做那件事了。WriteLine()会很好地工作。如果你想更新UI,你需要使用StateHasChanged()。 - H H
1
该参数在此声明中无效,只能在属性中有效。 - Ahmed Imam
1
太棒了,我很感激。 - Ahmed Imam
1
https://dev59.com/r7voa4cB1Zd3GeqP00to - Ahmed Imam

3
你可以创建一个新的类来存储想要传回父组件的参数。在本例中,我使用了一个通用复选框组件,我传递了一个Id和Checked属性,因为我需要知道在父组件中选择哪个项目以及它是否被选中。因此,事件需要知道Id和是否被选中。子组件包含自己的逻辑,然后传递一个赋值的新对象,其中包含所需的值,父组件现在可以使用这些值。
父组件
<Checkbox Id="@Id" Checked="@Item.Checked" CheckChanged="OnCheck" />

public class OnCheckEventArgs
{
    public bool IsChecked {get; set;}
    public long ItemId {get; set;}
}

public class ItemsOverview : ComponentBase
{
    public void OnCheck(OnCheckEventArgs args)
    {
        // do stuff
    }
}

子元素

<input type="checkbox" Id="@Id" checked="@Checked" @onchange="CheckboxChanged" />

public partial class Checkbox : ComponentBase
{
    [Parameter]
    public long Id {get; set;}

    [Parameter]
    public bool Checked {get; set;}

    [Parameter]
    public EventCallback<OnCheckEventArgs> CheckChanged {get; set;}

    protected async Task OnCheckChange(bool checked)
    {
        // do stuff
        await CheckChanged.InvokeAsync(new OnCheckEventArgs { IsChecked = checked, ItemId = @Id });
    }
}

2

您需要将其分配给只接收一个参数的事件回调函数,以便您可以创建字典或制作类并将其传递到对象中。

您将整个项目传递给父组件,然后您可以从此处获取id。

@foreach (var item in items)
{
    @foreach (var score in item.scores)
    {
        <span @onclick="OnItemClick.InvokeAsync(item)">
            @item.name
        </span>
    }
}

@code {
    [Parameter] public EventCallback<_TYPE_OF_YOUR_ITEM> OnItemClick { get; set; }
}

<Child OnItemClick="HandleItemClick">

@code {
   private void HandleItemClick(_TYPE_OF_YOUR_ITEM) 
   {
      // Handle your event here
   }
}

使用字典

@foreach (var item in items)
{
    @foreach (var score in item.scores)
    {
        <span @onclick="HandleClick(item, score.id)">
            @item.name
        </span>
    }
}

@code {
    [Parameter] public EventCallback<Dictionary<string, dynamic>> OnItemClick { get; set; }

    private void HandleClick(dynamic item, int score)
    {
        var parameter = new Dictionary<string, dynamic>();
        parameter.Add("Item", item);
        parameter.Add("ScoreId", score);

        OnItemClick.InvokeAsync(parameter);
}
}

   private void HandleItemClick(dictionary<string, dynamic> parameters) 
   {
      // extract your parameters and handle
      // parameters["ScoreId"], parameters["item"]

   }

1
哦,是的,你可以创建一个字典并传递一个字典类型,就像这样。 - DMHoffmann
1
我添加了一个使用字典的示例。 - DMHoffmann
1
你也可以传递你的整个分数。 - DMHoffmann
1
你的第一次尝试很接近 - 只需要 () => OnItemClick?.InvokeAsync(item)。参数是可以选择的。 - H H
2
是的,在直接绑定中,首选EventCallback。它是类型安全的,并自动调用StateHasChanged()。我认为这里并不重要。 - H H
显示剩余4条评论

1
我假设"ItemClicked"是EventCallback参数。如果是这样,您可以创建一个对象,如下:
Class Student
{
   public int Id { get; set; }
   public string Name { get; set; }
} 

然后你可以像这样使用:

父级

 private void ItemClicked(Student student)
    {
        Console.WriteLine(student.Name);
        Console.WriteLine(student.Id);
    }

孩子

<span @onclick = "ItemClicked(student)"> @item.name </span>

1
我的意图是从foreach循环内部传递名称和ID,但在您的回答中,您正在传递student,我不确定您从哪里获取它? - Ahmed Imam
1
我已经编辑了问题以便更好地理解。谢谢。 - Ahmed Imam

1

根据微软文档,也许你想要进行绑定?这是链接: https://learn.microsoft.com/en-us/aspnet/core/blazor/data-binding?view=aspnetcore-3.1

搜索 "Child-to-parent binding with chained bind"

<h1>Child Component</h1>
<input @oninput="OnPasswordChanged" 
   required 
   type="@(showPassword ? "text" : "password")" 
   value="@Password" />
@code {
    private bool showPassword;

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

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

    private Task OnPasswordChanged(ChangeEventArgs e)
    {
        Password = e.Value.ToString();

        return PasswordChanged.InvokeAsync(Password);
    }


}

父级元素:
<h1>Parent Component</h1>

<PasswordField @bind-Password="password" />

@code {
    private string password;
}

1
谢谢您的回答,但我确实需要在父组件中使用ItemClicked函数来执行一些操作,当子组件中的span被点击时。我理解了您的回答,但是当密码在父组件中发生变化时,您如何将其记录到控制台? - Ahmed Imam
1
抱歉,我不太理解你的评论问题。如果父级中的值发生了更改,您只需要执行stateHasChanged,它就应该被重新计算。我发现有时系统没有计算,我只需要通过更改一些顶级变量来强制执行它。我想有文档可以做到这一点...我现在记不清了。 - Jason Chen
1
我认为您也可以在父组件中编写事件处理程序,这样当子组件被点击时,您可以调用父组件中的事件处理程序。例如,父组件必须传递一个EventCallback。文档请参考此处:https://learn.microsoft.com/en-us/aspnet/core/blazor/event-handling?view=aspnetcore-3.1。 - Jason Chen

1

另一个回答:因为你改变了你的问题

可能是事件处理:https://learn.microsoft.com/en-us/aspnet/core/blazor/event-handling?view=aspnetcore-3.1

阅读此部分:EventCallback 并考虑 EventCallback

子组件:

触发父组件方法

[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }

父级:
<ChildComponent Title="Panel Title from Parent"
            OnClickCallback="@ShowMessage">
    Content of the child component is supplied
    by the parent component.
</ChildComponent>

@code{

    private void ShowMessage(MouseEventArgs e)
    {
        messageText = $"Blaze a new trail with Blazor! ({e.ScreenX}, {e.ScreenY})";
    }

}

你可能需要 @on{EVENT}:preventDefault

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接