Blazor - Calculando a Idade

Hoje vamos usar o Blazor para calcular a idade em uma aplicação SPA do lado do cliente sem usar JavaScript mas apenas C#.

Se você esta chegando agora e não sabe o que é o Blazor leia o artigo ASP .NET Core - Iniciando com o Blazor - Macoratti; se você já conhece e quer saber mais pode fazer o curso de Blazor Essencial.  

Hoje teremos uma aplicação bem simples que calcula a idade a partir da data de nascimento até uma data escolhida. Nesta aplicação veremos alguns recursos básicos do Blazor como uso de componentes e o cálculo da idade feita usando a linguagem C#.

Tudo isso rodando do lado do cliente em uma aplicação Single Page Application.

Recursos usados:

Criando o projeto Blazor (Cliente side) no VS Community 2019

Abra o VS 2019 Community (versão mínima 16.3) e selecione a opção Create a New Project;

A seguir selecione a opção Blazor app e clique em next;

Informe o nome do projeto :  Blazor_CalculaIdade, a localização e clique em Create;

A seguir teremos uma janela com duas opções :

  1. Blazor Server App
  2. Blazor WebAssembly App

Selecione a segunda opção - Blazor WebAssembly App - e deixe desmarcada a opção - ASP.NET Core hosted:

Assim vamos criar um projeto WebAssembly que roda do lado do cliente com a estrutura abaixo:

A pasta wwwroot é onde os recursos estáticos usados pela aplicação são colocados.

No arquivo Index.cshtml temos a inicialização da aplicação e a carga do WebAssembly.

As pastas Pages e Shared são as mais importantes do projeto e contém componentes que são arquivos com a extensão .razor.

Na pasta Pages temos os componentes roteados, ou seja, que possuem uma rota definida usando a diretiva @page.

Na pasta Shared temos os componentes não roteados e que podem ser compartilhados com os demais componentes.

O arquivo _Imports.razor é onde definimos os namespaces que poderão ser compartilhados com todos os componentes.

O arquivo App.razor é esta definindo o roteamento e o layout padrão usado no projeto.

No arquivo Startup.cs podemos configurar serviços e recursos da mesma forma que fazemos na ASP .NET Core.

Ajustando o projeto criado

Será criado um projeto padrão que vamos ajustar da seguinte forma:

  • Na pasta Pages vamos remover os arquivos FetchData.razor;
  • Na pasta Pages vamos alterar o nome do arquivo Counter.razor para Sobre.razor;
  • Na pasta Shared vamos remover o arquivo SurveyPrompt.razor;

Na pasta wwwroot vamos criar a pasta images e nesta pasta vamos incluir duas imagens que iremos usar em nosso projeto : calcidade1.jpg e maco1b.jpg

O arquivo NavMenu é onde definimos os links para o menu da aplicação. Vamos alterar o conteúdo deste arquivo conforme abaixo:

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">Blazor_CalculaIdade</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-calculator" aria-hidden="true"></span> Calcula Idade
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="sobre">
                <span class="oi oi-book" aria-hidden="true"></span> Sobre
            </NavLink>
        </li>
    </ul>
</div>
@code {
    bool collapseNavMenu = true;
    string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
    void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }

Alteramos os links do menu para exibir os links com os textos: Calcula Idade e Sobre

Alterando o código do componente Sobre.razor

O arquivo Sobre.razor é um componente onde usando a diretiva @page definimos a rota '/sobre' para acessar este componente. Também estamos exibindo a imagem maco1b.jpg.

Aqui temos somente código HTML:

@page "/sobre"
<div>
    <img src="/images/maco1b.jpg" />
</div>
<hr />
<h4>
    Aprenda mais sobre Blazor na Macoratti.net
</h4>
<div>
    <a href="http://www.macoratti.net/curso_blazor1.htm">Curso de Blazor Essencial </a>
</div>

Alterando o código do componente Index.razor

O componente Index.razor é o componente principal do nosso projeto e onde vamos definir o cálculo da idade.

Neste arquivo temos a diretiva @code onde definimos código C# para fazer o cálculo da idade.

@page "/"
    <div>
        <img src="/images/calcidade1.jpg" />
    </div>
<p>
   Data de Nascimento : <input @onchange="@((args) => { nascimento = Convert.
ToDateTime((string)args.Value); CalculaIdade(); })" type="date" />
</p>
<p>Calcular a idade até : <input @bind="@ate" type="date" /></p>
<p><button @onclick="InserirHoje">Inserir data atual</button></p>
<p>
    Sua Idade é : @idade anos
</p>
@code {
    DateTime nascimento = new DateTime(1965, 12, 15);
    DateTime ate = DateTime.Now;
    double idade;

    void InserirHoje()
    {
        ate = DateTime.Now;
    }
    void CalculaIdade()
    {
        idade = ate.Year - nascimento.Year;
        if (ate.DayOfYear < nascimento.DayOfYear)
        {
            idade = idade - 1;
        }
    }
}

Vamos entender o código :

1- Definimos um tag input do tipo 'date' onde temos o evento @onchange que vai chamar o método CalculaIdade quando a entrada da data for alterada. Aqui estamos convertendo os argumentos passados no formato string para DateTime:

<input @onchange="@((args) => { nascimento = Convert.ToDateTime((string)args.Value); CalculaIdade(); })" type="date" />

2- A seguir temos outra tag input do tipo date que usa o atributo @bind fazendo a vinculação bidirecional, ou seja o databinding:

<p>Calcular a idade até : <input @bind="@ate" type="date" /></p>

3- Depois temos um button html onde definimos um evento @onclick que executa o método InserirHoje:

<p><button @onclick="InserirHoje">Inserir data atual</button></p>

4- Concluindo usamos o databinding unidirecional para exibir o valor da variável idade:

Sua Idade é : @idade anos

Agora temos a definição do código C# na diretiva @code:

1 - Definimos as variáveis usadas no código:

     DateTime nascimento = new DateTime(1965, 12, 15);
    DateTime ate = DateTime.Now;
    double idade;

2 - Temos o método InserirHoje que inclui a data atual na variável ate:

    void InserirHoje()
    {
        ate = DateTime.Now;
    }

3 - E o método CalculaIdade que faz o cálculo da idade :

  void CalculaIdade()
    {
        idade = ate.Year - nascimento.Year;
        if (ate.DayOfYear < nascimento.DayOfYear)
        {
            idade = idade - 1;
        }
    }

Executando o projeto iremos obter o resultado abaixo:

Tudo muito bom, mas podemos melhorar o projeto, e, para isso vamos criar um componente chamado Aviso na pasta Shared que será um componente não roteado que vamos usar para exibir um aviso genérico no projeto.

Crie o arquivo Aviso.razor na pasta Shared e inclua o código abaixo:

@if (Exibir)
{
    <div class="alert alert-secondary mt-4" role="alertdialog">
        @ChildContent
    </div>
}
@code {
    [Parameter]
    public bool Exibir { get; set; }
    [Parameter]
    public RenderFragment ChildContent { get; set; }
}

Neste componente usamos alguns recursos do Blazor como Parameter, ChildContent e RenderFragment.

Os componentes podem ter parâmetros de componente, que são definidos usando propriedades públicas na classe de componente com o atributo [Parameter]. Usamos atributos para especificar argumentos para um componente no código de marcação HTML.

No código acima, o componente Aviso tem uma propriedade ChildContent que representa um RenderFragment, que representa um segmento de interface do usuário a ser renderizado. O valor de ChildContent é posicionado na marcação do componente onde o conteúdo deve ser renderizado. O valor de ChildContent é recebido do componente pai e renderizado dentro do panel-body do painel de inicialização.

Assim RenderFragment pode renderizar qualquer conteúdo como código de marcação.

Agora que temos o nosso componente pronto vamos usá-lo no componente Index.

Para isso definimos a tag :

<Aviso Exibir="Exibir">
    <h5>@Mensagem</h5>
</Aviso>

- Exibir é uma variável do tipo booleana que indica se vamos exibir ou não o aviso;
- Mensagem é um parâmetro onde vamos definir o texto da mensagem que vamos exibir;

Assim teremos que definir no componente Index a variável booleand Exibir e o parâmetro Mensagem.

Veja como ficou o código:

@page "/"
    <div>
        <img src="/images/calcidade1.jpg" />
    </div>
<p>
   Data de Nascimento : <input @onchange="@((args) => { nascimento = Convert.
ToDateTime((string)args.Value); CalculaIdade(); })" type="date" />
</p>
<p>Calcular a idade até : <input @bind="@ate" type="date" /></p>
<p><button @onclick="InserirHoje">Inserir data atual</button></p>
<p>
    Sua Idade é : @idade anos
</p>
<Aviso Exibir="Exibir">
    <h5>@Mensagem</h5>
</Aviso>
@code {
    DateTime nascimento = new DateTime(1965, 12, 15);
    DateTime ate = DateTime.Now;
    double idade;

    private bool Exibir = false;
    [Parameter]
    public string Mensagem { get; set; }
    void InserirHoje()
    {
        ate = DateTime.Now;
    }
    void CalculaIdade()
    {
        idade = ate.Year - nascimento.Year;
        if (ate.DayOfYear < nascimento.DayOfYear)
        {
            idade = idade - 1;
        }
        DateTime DataNascimento = nascimento;
        DateTime DataAtual = ate;
        int Anos = new DateTime(DateTime.Now.Subtract(DataNascimento).Ticks).Year - 1;
        DateTime AnosTranscorridos = DataNascimento.AddYears(Anos);
        int Meses = 0;
        for (int i = 1; i <= 12; i++)
        {
            if (AnosTranscorridos.AddMonths(i) == DataAtual)
            {
                Meses = i;
                break;
            }
            else if (AnosTranscorridos.AddMonths(i) >= DataAtual)
            {
                Meses = i - 1;
                break;
            }
        }
        int Dias = DataAtual.Subtract(AnosTranscorridos.AddMonths(Meses)).Days;
        int Horas = DataAtual.Subtract(AnosTranscorridos).Hours;
        int Minutos = DataAtual.Subtract(AnosTranscorridos).Minutes;
        int Segundos = DataAtual.Subtract(AnosTranscorridos).Seconds;
        Exibir = true;
        Mensagem = $"Ou sendo mais preciso... {Anos} anos {Meses} Meses {Dias} dias {Horas} horas " +
                            $"{Minutos} minutos {Segundos} segundos";
    }

 

O resto é apenas código C# que será compilado e executado no navegador.

Agora o resultado final ficou assim:

Pegue o código do projeto aqui:  Blazor_CalculaIdade.zip  (sem as referências)

"Qual é mais fácil? Dizer ao paralítico: Estão perdoados os teus pecados, ou dizer: Levanta-te, toma o teu leito e anda?
Ora, para que saibais que o Filho do Homem tem sobre a terra autoridade para perdoar pecados — disse ao paralítico:  Eu te mando: Levanta-te, toma o teu leito e vai para tua casa."

Marcos 2:9-11
 

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?


Referências:


José Carlos Macoratti