Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to mutate a component property in blazor

I have two components, Child.razor and Parent.razor.

The Child.razor HTML:

<input type="text" value="@Text" />

The Child.razor C#:

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

And the Parent.razor HTML:

<Child @ref="child_1" />
<Child @ref="child_2" />
<Child @ref="child_3" />

Parent.razor C#:

Child child_1;
Child child_2;
Child child_3;

void SetText(Child item, string text)
{
    item.Text = text;
}

I get a warning on the item.Text = text:

Warning BL0005: Component parameter 'Text' should not be set outside of its component.

After some googling, I found this question: BL0005 - external parameter usage - why is a warning for that?

The answer is great, but it does not provide an alternative (the linked content on github is also not very helpful).

What is the correct way to mutate a component parameter from the parent?

EDIT

To clarify a bit more: I know I could use binding, but I need to be able to change the value inside the SetText method, passing the Child I want to mutate as a parameter. The problem with binding is that the variable is not tied with the component. In other words: with the referente to the Child, I am not able to know which binding string I should set.

For example:

<Child @ref="child_1" @Text="binding_1" />
<Child @ref="child_2" @Text="binding_2"/>
<Child @ref="child_3" @Text="binding_3"/>

Parent.razor C#:

Child child_1;
Child child_2;
Child child_3;

string binding_1;
string binding_2;
string binding_3;

void SetText(Child item, string text)
{
     // which binding string should I set?
}

I can visualize some funky code, creating a Dictionary<Child, string> to correlate the Component to the binding string, or something like that, but... really?

like image 410
Guilherme Avatar asked Dec 17 '19 20:12

Guilherme


People also ask

How do you transfer data from one component to another in Blazor?

There are three steps to this solution: Define an event callback in your first component. Define a parameter in your second component. Define a property in your parent component (your page).

How do you pass parameters in Blazor?

By using Blazor route parameters, you can pass values from one page to another page. Use NavigationManager to pass a value and route the parameter to another page. Follow this example to achieve passing values from one page to another. Get the passed Page1 parameter value in Page2.

What is OnInitializedAsync in Blazor?

Blazor apps that prerender their content on the server call OnInitializedAsync twice: Once when the component is initially rendered statically as part of the page. A second time when the browser renders the component.

What is a Razor component?

Blazor apps are built using Razor components, informally known as Blazor components. A component is a self-contained portion of user interface (UI) with processing logic to enable dynamic behavior. Components can be nested, reused, shared among projects, and used in MVC and Razor Pages apps.


1 Answers

You can define a property of type Child in the parent component pass a reference of the parent component (this) to the child component property of Parent type. Now the child component hold a reference to the parent component, and it can add itself (again using this) to the parent. Now you have a reference to the child component, and you can set its Text property to something interesting. I hope I'm clear, if not I'll post code to reflect this. The following code works...

Child.razor

<input type="text" value="@Text" />

@code
{
    [Parameter] public string Text { get; set; }
    public void SetText(string text)
    {
        Text = text;
        StateHasChanged();
    }
    [ParameterAttribute] public Parent Parent { get; set; }
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            Parent.AddToParent(this);
        }
    }
}

Note that the original component parameter Text's value assigned in the parent component (Text="Some Text") is not visible in the text box because immediately after the Parent's SetText method calls the Child's SetText method, which in return assign the value passed to it to the Text property, and thus the value seen in the text box is "new text"

Parent.Razor

<Child Parent="this" Text="Some Text" />

@code{
    public void AddToParent(Child child)
    {
        string text = "new text";
        SetText(child, text);
    }

    void SetText(Child item, string text)
    {
        // which binding string should I set?
        item.SetText(text);

    }
}

Usage

<Parent />
like image 166
enet Avatar answered Nov 15 '22 20:11

enet