简体   繁体   中英

How to change Button Text by calling another component method in Blazor

I have a custom Button component like below.

<button class="btn btn-outline-primary" @onclick="OnClick"> @ButtonText</button>

@code {

    [Parameter]
    public string ButtonText { get; set; } = "Edit";

    public virtual void OnClick()
    {
        ButtonText = ButtonText == "Edit" ? "Editing..." : "Edit";
    }
}

When I click button every thing works as excepted and Button text is changing. But when i click on another button i want to change the text of the button.To do this I call the button's onclick method. But when I click the button, the text does not change even though the method is called. Here is my page.

@page "/test"

<EditButton @ref="EditButton"></EditButton>

<button class="btn-primary" @onclick="ChangeButtonText">Change Button Text</button>

@code {

    EditButton EditButton;

    void ChangeButtonText()
    {
        EditButton.OnClick();
    }
}

It's partly due to your architectural design: The ButtonComponent should not be managing the editing-status, it should just display it.

@page "/test"

<EditButton IsEditing="isEditing" Click="EditClick"></EditButton>

<button class="btn-primary" @onclick="ChangeButtonText">Change Button Text</button>

@code {

    //EditButton EditButton;
    bool isEditing = false;

    void ChangeButtonText()
    {
        isEditing = false;  // or !isEditing
    }

    void EditClick()
    {
       isEditing = ! isEditing;   
    }

}

Your code does not work simply because it lacks a call to the StateHasChanged method:

EditButton.razor

<button class="btn btn-outline-primary" @onclick="OnClick"> @ButtonText</button>

@code {

    [Parameter]
    public string ButtonText { get; set; } = "Edit";

    public void OnClick()
    {
        ButtonText = ButtonText == "Edit" ? "Editing..." : "Edit";

        InvokeAsync(() => StateHasChanged());
    }
} 

Note That I added a call to the StateHasChanged method to re-render the component after its state has changed.

InvokeAsync(() => StateHasChanged());

Index.razor

@page "/"

<EditButton @ref="EditButton"></EditButton>

<button class="btn-primary" @onclick="ChangeButtonText">Change Button Text</button>

@code {

    EditButton EditButton;

    void ChangeButtonText()
    {
        EditButton.OnClick();
    }
}

To sum up: What you do is fine, but you must call the StateHasChaged method manually. It is not called automatically by the framework. Note that it is not necessary to add a call to the StateHasChaged method from event handler that handle UI event, such as the 'click' event. But in your case it is necessary, as the EditButton.OnClick event handler is not a UI event handler. That was the only issue with your code.

IMPORTANT: You should not modify or change the state of a Component parameter property. This should be avoided:

[Parameter]
public string ButtonText { get; set; } = "Edit";

As well as this:

ButtonText = ButtonText == "Edit" ? "Editing..." : "Edit";

Component parameter properties should be automatic properties:

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

And they must never be modified outside of the component. Read this Read this . Instead you should define local variable or properties that are assigned from the component parameter properties' values, on which you can apply whatever manipulations you want.

Not adhering to that rule may result in unfavorable side effects in large components, only Steve Sanderson can discern.

What about this simple solution. EditButton remains the same.

@page "/"

<EditButton ButtonText="@this.editButtonText" ></EditButton>

<button class="btn btn-primary ml-3" @onclick="ChangeButtonText">Change Button Text</button>

@code {
    string editButtonText = "Edit";

    void ChangeButtonText()
    {
        editButtonText = editButtonText.Equals("Edit")
        ? "Editing"
        : "Edit";
    }
}

You don't need to hook up callbacks and references. When you change the value of ButtonText on your component and trigger a Blazor Component event handler - ChangeButtonText - on the parent, the Renderer detects the change to ButtonText and informs EditButton by calling SetParametersSetAsync . This precipitates a render event on EditButton and the button text gets updated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM