Marcus Vinicius
Marcus Vinicius

Reputation: 1

Blazor: Not triggering @if check when variable is changed in the code

I have a .razor page in my Blazor.Server program called EditPerson.razor.

This page is opened when the user does a double click on a table row in another page.

The page initialize doing a GET request to the API that return that person's data based on the id passed in the URL parameter.

In the html/razor part I have two components that are the main form for the person's personal data and a tab area for addresses and contact info.

Then I have tow @ifchecks that control the show of two modals dialog, one for errors and other for the success message.

The problem is that when I change the boolean variable to show the success message, the @if checks are not triggered and the modal is never show.

This is the html/razor code for example:

@page "/pessoas/edit/{PessoaId}"

@inject IPessoaApiService _apiService
@inject NavigationManager _uriHelper;

@using Ekklesia.Web.Library.Models.Pessoa
@using Ekklesia.Web.Library.Models.UI.Modais
@using Core.Enums
@using Ekklesia.Web.Library.Interfaces

<PageTitle>Ekklesia - Editar Pessoa</PageTitle>

<div id="pessoa-insert" class="container-fluid p-2">

    <div class="card ekklesia-form">
        <div class="card-header">
            <h1 class="display-4 ps-2 pt-1">Editar Pessoa</h1>
        </div>
        <div class="card-body">
            <PessoaDadosForm Pessoa="Pessoa" @ref="PessoaDadosForm" />
            <GradePessoa Pessoa="Pessoa" />
            
        </div>
        <div class="card-footer">
            <div class="d-flex flex-row-reverse m-2 me-2">
                <div class="ms-3">
                  <SfButton CssClass="e-primary"
                        @onclick="Update">
                    <i class="fa-solid fa-check me-2"></i>Salvar
                  </SfButton></div>
                <div>
                  <SfButton CssClass="e-secundary"
                        @onclick="Voltar">
                    <i class="fa-solid fa-ban me-2"></i>Voltar
                  </SfButton></div>
            </div>
        </div>          
    </div>
    
    @if (_showErrorModal)
    {
        <ModalBase Modal="@_erroModal"
            OnFecharModal="@OnFecharModalErro"/>
    }
    
    @if (_showSuccessModal)
    {
        <ModalBase Modal="@_successModal"
            OnFecharModal="@OnFecharModalSucesso"/>
    }

And here is the @code part:

@code {

    #region Parâmetros e campos internos

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

    private PessoaDadosForm? PessoaDadosForm { get; set; }

    private PessoaViewModel _pessoa = new();

    private PessoaViewModel Pessoa
    {
        get { return _pessoa ?? new(); }
        set { _pessoa = value; }
    }

    private bool _showErrorModal = false;
    private ModalBaseViewModel _erroModal = new();
    
    private bool _showSuccessModal = false;
    private ModalBaseViewModel _successModal = new();

    #endregion

    #region Overrides

    protected override async Task OnInitializedAsync()
    {
        var response = await _apiService.Get(pessoaId: Convert.ToInt32(PessoaId));

        if (response.Success 
            && response.StatusCode is HttpStatusCode.OK)
        {
            if (response.Data is not null)
            {
                var pessoa = response.Data.SingleOrDefault();
                Pessoa = pessoa ?? throw new Exception($"A busca pela pessoa de ID {PessoaId} retornou nula");
            }
        }
    }

    #endregion

    #region Métodos da page

    private async Task Update()
    {
        Pessoa.Sexo = (SexoEnum)PessoaDadosForm.SexoInt;
        Pessoa.Tipo = (TipoPessoaEnum)PessoaDadosForm.TipoInt;
        Pessoa.Status = StatusEnum.Ativo;

        var response = await _apiService.Update(Pessoa, Convert.ToInt32(PessoaId));

        if (response.StatusCode is HttpStatusCode.OK)
        {
            var resultado = response.Data ?? Pessoa;
            _pessoa = new();
            
            AbrirModalSucesso("A atualização foi um sucesso.", response.Message);
        }
        else
        {
            List<KeyValuePair<string, string>> erros = new();

            response.Errors.ForEach(e =>
            {
                erros.Add(
                    new(e.Field == "DataNascimento" ? "Data Nascimento" : e.Field, e.Message));
            });

            AbrirModalErro("A inserção da nova pessoa falhou.", response.Message, erros);
        }
    }

    private void Voltar()
    {
        _pessoa = new();
        _uriHelper.NavigateTo("/pessoas");
    }

    #endregion

    #region Modais

    private void OnFecharModalErro()
    {
        InicializarModalErro();

        _erroModal.ModalClass = "fade";
        _erroModal.ModalDisplay = "hidden";
        _erroModal.ShowBackdrop = false;

        _showErrorModal = false;
    }
    
    private void OnFecharModalSucesso()
    {
        InicializarModalSucesso();

        _successModal.ModalClass = "fade";
        _successModal.ModalDisplay = "hidden";
        _successModal.ShowBackdrop = false;

        _showSuccessModal = false;
        
        _uriHelper.NavigateTo("pessoas");
    }

    private void AbrirModalErro(string texto, string descricao, List<KeyValuePair<string, string>> erros)
    {
        InicializarModalErro();

        _erroModal.Texto = texto;
        _erroModal.Descricao = descricao;
        _erroModal.Erros = erros;

        _erroModal.ModalClass = "show";
        _erroModal.ModalDisplay = "block";
        _erroModal.ShowBackdrop = true;
        
        _showErrorModal = true;
    }
    
    private void AbrirModalSucesso(string texto, string descricao)
    {
        InicializarModalSucesso();

        _successModal.Texto = texto;
        _successModal.Descricao = descricao;

        _successModal.ModalClass = "show";
        _successModal.ModalDisplay = "block";
        _successModal.ShowBackdrop = true;
        
        _showSuccessModal = true;
    }

    private void InicializarModalErro()
    {
        _erroModal = new() 
        {
            Titulo = "Ocoreu um erro", 
            ModalTipo = "modal-erro", 
            ModalBotaoPrincipalTexto = "Entendi"
        };
    }
    
    private void InicializarModalSucesso()
    {
        _successModal = new()
        {
            Titulo = "Sucesso", 
            ModalTipo = "modal-sucesso", 
            ModalBotaoPrincipalTexto = "Ok"
        };
    }

    #endregion
}

The success message modal is to been opened in this portion:

private void AbrirModalSucesso(string texto, string descricao)
    {
        InicializarModalSucesso();

        _successModal.Texto = texto;
        _successModal.Descricao = descricao;

        _successModal.ModalClass = "show";
        _successModal.ModalDisplay = "block";
        _successModal.ShowBackdrop = true;
        
        _showSuccessModal = true;
    }

Here is where the modal data is prepared:

private void InicializarModalSucesso()
    {
        _successModal = new()
        {
            Titulo = "Sucesso", 
            ModalTipo = "modal-sucesso", 
            ModalBotaoPrincipalTexto = "Ok"
        };
    }

This is the modal code:

@using Ekklesia.Web.Library.Models.UI.Modais

<div class="modal @Modal.ModalClass" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" style="display:@Modal.ModalDisplay">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header ekklesia-modal-header @Modal.ModalTipo">
                <h5 class="modal-title">@Modal.Titulo</h5>
            </div>
            <div class="modal-body">
                <div class="ekklesia-form">
                    <div class="d-sm-flex flex-row">
                        <div class="col-sm">
                            <div class="modal-texto">
                                @Modal.Texto
                            </div>
                            <div class="modal-descricao">
                                @Modal.Descricao
                                @if (Modal.ModalTipo == "modal-erro")
                                {
                                    @if (Modal.Erros.Count > 0)
                                    {
                                        <div class="card p-1 mt-3">
                                            <div class="card-body p-1">
                                                @foreach (var erro in @Modal.Erros)
                                                {
                                                    <div>
                                                        <b>Campo:</b> @erro.Key <br/>
                                                        <b>Erro:</b> @erro.Value
                                                    </div>
                                                    <hr />
                                                }
                                            </div>
                                        </div>
                                    }
                                }
                            </div>
                        </div>
                    </div>
                </div>                    
            </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-outline-@(Modal.ModalTipo == "modal-erro" ? "danger" : "success")" 
                    @onclick="Confirm">@Modal.ModalBotaoPrincipalTexto</button>
        </div>
        </div>
    </div>
</div>


@if (Modal.ShowBackdrop)
{
    <div class="modal-backdrop fade show"></div>
}

@code {

    [Parameter]
    public ModalBaseViewModel Modal { get; set; } = new();
    
    [Parameter]
    public EventCallback OnFecharModal { get; set; }

    private async Task Confirm()
    {
        await OnFecharModal.InvokeAsync();
    }

}

I have another page for creating new persons and in there I used the same aproach for the modals and worked there.

I have tried to invoke the StateHasChanged() method in different parts of the process but it changed noting.

I have tried for some 4 hours to resolve this before asking for help here.

Please, if anyone can help, I will be very gratefull!

P.S.: This is my very first question here, if more info is needed please comment bellow that I will be watching for tips.

I am from Brazil, that's is why some parts of the code have portuguese words.

I am using some Syncfusion components in those code examples.

This is how the page looks rigth now: Edit page print

Upvotes: 0

Views: 1303

Answers (1)

noel
noel

Reputation: 543

Without being able to test your code right now, my first suggestion would be to try and call StateHasChanged() after updating _showErrorModal

Upvotes: 1

Related Questions