how to call child component method from parent component in blazor?
Asked Answered
P

3

50

i have two component. The first component includes list of model and the second component contains modal form I want to click on the model when inside the first component In the second component, open modal and edit the model how to call show function in child component from parent component

<ChildComponent />
<button onClick="@ShowModal">show modal</button>

@code{
    ChildComponent child; 

    void ShowModal(){
        child.Show();
    }
}

i'm used @using but this code has error :

the type or namespace name ChildComponent coud not be found

Plastid answered 3/2, 2020 at 14:50 Comment(0)
K
93

First you need to capture a reference of your child component:

<ChildComponent @ref="child" />

Then you can use this reference to call the child's component methods as you do in your code.

<button onClick="@ShowModal">show modal</button>

@code{
    ChildComponent child; 

    void ShowModal(){
        child.Show();
    }
}

The namespace of your component need to be added by a using either in the page or in _Imports.razor. If your component is in the sub folder Components/ChildComponent.razor then its namespace is {YourAppNameSpace}.Components

@using MyBlazorApp.Components

read the code

Kenzi answered 3/2, 2020 at 15:27 Comment(4)
How would you write this with child components rendered in a foreach loop?Foxe
@JasonAyer With an other component containing the ChildComponent and the show modal button for the ChildComponent. So, just foreach this one actually.Kenzi
I just tried that using your code as an example as is and it only calls the method from the last component rendered. not all of them.Foxe
Added - #62520075Foxe
V
4

Here is an article I just posted on the subject using Interfaces:

https://datajugglerblazor.blogspot.com/2020/01/how-to-use-interfaces-to-communicate.html

In this example, the Index page is an IBlazorComponentParent object.

On the Login Component, the cool part is to set the Parent property, you just set Parent=this:

enter image description here

The way it works is the setter for the Parent property on the Login component calls the Register method on the parent:

[Parameter]
public IBlazorComponentParent Parent
{
    get { return parent; }
    set 
    { 
        // set the parent
        parent = value;

        // if the value for HasParent is true
        if (HasParent)
        {
            // Register with the parent to receive messages from the parent
            Parent.Register(this);
        }
    }
}

Then on the parent component or page, the Register method stores the reference to the component:

public void Register(IBlazorComponent component)
{
    // If the component object and Children collection both exist
    if (NullHelper.Exists(component, Children))
    {
        // If this is the Login component
        if (component.Name == "Login")
        {
            // Set the Login control
            this.Login = component as Login;
        }

        // add this child
        Children.Add(component);
    }
}

At this point, the parent and the Login page can communicate with each other as they both contain a ReceiveData method where you can send messages.

Valor answered 4/2, 2020 at 0:22 Comment(0)
B
2

I had to communicate between one parent <==> multiple children. The children were created in a foreach loop for a list, so I could not use ref like the answer from "agua from mars".

The answer from "user12228709" seemed usable, but it was too cumbersome to implement with all the interfaces and whatnot. So, I used the same principle but made it simpler by just creating a mediator object and let parent/children communicate through it.

So, create a mediator class that has events, and methods to raise those events, something like

public class Mediator
{
    public event EventHandler<string> SomethingChanged;
    public void NotifySomethingChanged()
    {
        Task.Run(() =>
        {
            SomethingChanged(this, "test");
        });
    }
}

And then, in the @code of the parent component, create an instance, and passe that to children as a parameter

<ChildComponent MediatorInstance="@MediatorInstance" />

@code
{
      Mediator MediatorInstance = new();

Of course, the child receives that as a parameter.

@code
{
    [Parameter]
    public Mediator MediatorInstance{ get; set; }

Now, bi-directional communication can be done. The side that wants tell others to do something calls a method like NotifySomethingChanged, and the receivers subscribe to relevant events at initialisation.

Brash answered 10/12, 2022 at 10:8 Comment(1)
All nice but how do I keep the component from being rendered?Megaron

© 2022 - 2024 — McMap. All rights reserved.