Home > Blockchain >  How to re-render another a component from another component in Blazor?
How to re-render another a component from another component in Blazor?

Time:11-20

So, basically, I have a periodic-table webapp that looks like this:

enter image description here

When I click on a family (the ones at the top center of the screen) I want every element that is not part of this family to lower its brightness.

This is how I'm doing it:

HeaderView.razor:

[Parameter, EditorRequired] public List<ElementDataModel> ElementDataModels { get; set; } = default!;

public void OnFamilyClick(Family family)
    {
        foreach(var elementDataModel in ElementDataModels)
        {
            elementDataModel.Brightness = elementDataModel.Family.Equals(family) ? 100 : 60;
        }
    }

The DataModel for every Element is being created this way in PeriodicTableView.razor:

public List<ElementDataModel> ElementDataModels { get; set; } = new();

    protected override void OnInitialized()
    {
        foreach (var element in Element.All)
        {
            ElementDataModels.Add(new ElementDataModel(element));
        }
    }

The logic is working, I debugged and the brigthness property is indeed changing. But I got no UI changes. What is the mistake? Did I miss some StateHasChanged()? How do I re-render the PeriodicTableView.razor with the new Brigthness values?

Thanks

edit: the brightness bind:

<div style="filter: brightness(@($"{DataModel.Brightness}%"))">
@code{
    [Parameter, EditorRequired] public ElementDataModel DataModel { get; set; } = default!;
}

ElementDataModel:

public class ElementDataModel 
{
    public ElementDataModel(Element initialValue)
    {
        Brightness = 100;
        AtomicMass = initialValue.AtomicMass;
        Electronegativity = initialValue.Electronegativity;
        IonizationEnergy = initialValue.IonizationEnergy;
        Symbol = initialValue.Symbol;
        Name = initialValue.Name;
        ElectronConfiguration = initialValue.ElectronConfiguration;
        AtomicNumber = initialValue.AtomicNumber;
        OxidationStates = initialValue.OxidationStates;
        Family = initialValue.Family;
        Row = initialValue.Row;
        Column = initialValue.Column;
    }

    public int Brightness { get; set; }
    public double AtomicMass { get; }
    public double? Electronegativity { get; }
    public double? IonizationEnergy { get; }
    public string Symbol { get; }
    public string Name { get; }
    public ElectronConfiguration ElectronConfiguration { get; }
    public int AtomicNumber { get; }
    public List<int> OxidationStates { get; }
    public Family Family { get; }
    public int Row { get; }
    public int Column { get; }

}

CodePudding user response:

Yeah, I think the change of state flag doesn't propagate to parent, so your main view doesn't know anything has happened in HeaderView. There might be a simpler way, but I think something like the following should work:

HeaderView.razor

   [Parameter]
    public EventCallback OnFamilyChanged { get; set; }
    
    public async Task OnFamilyClick(Family family)
        {
            foreach(var elementDataModel in ElementDataModels)
            {
                elementDataModel.Brightness = elementDataModel.Family.Equals(family) ? 100 : 60;
            }
            await OnFamilyChanged.InvokeAsync();
        }

PeriodicTableView.razor

<HeaderView OnFamilyChanged=HandleFamilyChanged />
@code {

    [Parameter, EditorRequired] public List<ElementDataModel> ElementDataModels { get; set; } = default!;

    public async Task HandleFamilyChanged(){
            await InvokeAsync(StateHasChanged);
    }
}
  • Related