1
votes

In my component, I have a child component (FooComponent) where I pass a parameter to it and also get a ref.

Parent.razor

<FooComponent @ref="FooComponentRef" FooParameter="@MyValue"/>
    
<button @onclick="Test">@MyValue</button>
    
@code {
    FooComponent FooComponentRef { get; set; }
    
    string MyValue { get; set; }
    
    int count { get; set; }
    
    void Test(){
        MyValue = "SomeValue" + count++;            
        FooComponentRef.FooFunction();
    }
}

I modified the code so it's a simple and testable example

And I have a function (Test) that will update the property that is passed in the parameter (MyValue passed to FooParameter) and call a function from the ref (FooFunction of FooComponent).

And inside the FooComponent

FooComponent.razor

<div>
    <div>FooParameter: @FooParameter</div>
    <div>ValueUsedInFooFunction: @ValueUsedInFooFunction</div>
</div>

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

    public string ValueUsedInFooFunction { get; set; }

    public void FooFunction()
    {
        // This function is using FooParameter to make some logic
        ValueUsedInFooFunction = FooParameter;
    }
}

I modified the code so it's a simple and testable example

It uses the FooParameter in the FooFunction to do some logic.

The problem is that when I change the MyValue and call FooFunction, the component didn't update yet, so it uses the "old" value of FooParameter, but I need to use the new setted value, which is the correct MyValue.

Another thing that makes this hard to solve is that I can't change the FooFunction (it's not a function that I created).

I have tried using everything (StateHasChanged, InvokeAsync) but still no solution.

What I need is my Test function to do something like

void Test(){
    MyValue = "SomeValue" + count++;   
    
    // Somehow update UI so FooParameter have the correct value of MyValue          
    
    FooComponentRef.FooFunction();    
}

Here is the blazor fiddle to test

In the fiddle, when clicking in the button and calling Testfunction, you will see that the ValueUsedInFooFunction is always the "old" value of FooParameter, meaning that the FooFunction is being executed before the FooParameter is being updated.

2

2 Answers

0
votes

This change will make this work:

 void Test(){
    MyValue = "SomeValue" + count++;    
    FooComponentRef.FooParameter = MyValue;
    FooComponentRef.FooFunction();
}
0
votes

Instead of passing the string parameter (MyValue), you will pass an object, a Dto, that has one string property that will contain the value. This is the Dto:

   public class FooDto
{
    public string MyValue { get; set; }
}

This is Index:

  @page "/"
@using WebApplication2.Models

<FooComponent @ref="FooComponentRef" FooDtoParameter="@_dto" />

<button @onclick="Test">@MyValue</button>

@code {
    FooComponent FooComponentRef { get; set; }

    string MyValue { get; set; }

    int count { get; set; }

    /// <inheritdoc />
    protected override void OnInitialized()
    {
        base.OnInitialized();
        
    // The Dto class will be passed as a parameter to foo.
    _dto = new FooDto();
    }

    void Test()
    {
        _dto.MyValue = "SomeValue" + count++;

        FooComponentRef.FooFunction();
    }

    
    private FooDto _dto;
}

Foo:

@using WebApplication2.Models
<div>
    <div>FooParameter: @FooDtoParameter.MyValue</div>
    <div>ValueUsedInFooFunction: @ValueUsedInFooFunction</div>
</div>

@code {
    [Parameter]
    public FooDto FooDtoParameter { get; set; }

    public string ValueUsedInFooFunction { get; set; }

    public void FooFunction()
    {
    // This function is using FooParameter to make some logic
        ValueUsedInFooFunction = FooDtoParameter.MyValue;
    }
}

The Child and parent component are using the same Dto object to communicate, when you change the value of the property, the child component has instant access to that information.

I understand there may be better ways to do this, but I am trying to answer the question on this specific case.