38

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

reza malekmohamadi
  • 507
  • 1
  • 8
  • 14

3 Answers3

81

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

agua from mars
  • 16,428
  • 4
  • 61
  • 70
  • 4
    How would you write this with child components rendered in a `foreach` loop? – Jason Ayer Jun 22 '20 at 15:41
  • 1
    @JasonAyer With an other component containing the `ChildComponent` and the show modal button for the ChildComponent. So, just foreach this one actually. – agua from mars Jun 22 '20 at 16:06
  • 1
    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. – Jason Ayer Jun 22 '20 at 16:26
  • 1
    Added - https://stackoverflow.com/questions/62519575/how-to-call-child-component-method-from-parent-component-with-foreach – Jason Ayer Jun 22 '20 at 16:55
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.

1

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.

Damn Vegetables
  • 11,484
  • 13
  • 80
  • 135