Skip to content
Advertisement

Razor Pages – Keep track of Date field on changes on screen

I Have a month selector to choose the month of some some bills, but I want to create auxiliar button to easy navigation to +1 and -1 month.

When I do any kind of Post to my server side page, my DateTime is Reset to default value (01-01-0001) and I lost all track of the value, is there a correct way to manipulate this kind o situation without losing the value of the field?

My Methods (even tryied to pass the date instead of just passing an int to addmonths take care but didn’t work either)

    public PartialViewResult OnPostMonthSelector([FromBody] string dataAtualizada)
    {
        dataCorrente = DateTime.ParseExact(dataAtualizada, "yyyy-MM", null);
        //contas = contaDTO.buscaContasUsuario(User.Identity.Name).Where(c => c.Data.Month == dataCorrente.Month && c.Data.Year == dataCorrente.Year).ToList();
        contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
        return Partial("_PartialContas", contas);
    }

    public PartialViewResult OnPostMonthNextButton([FromBody] string data)
    {
        dataCorrente = DateTime.ParseExact(data, "yyyy-MM", null).AddMonths(1);
        contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
        return Partial("_PartialContas", contas);
    }
    public PartialViewResult OnPostMonthPrevButton([FromBody] string data)
    {
        dataCorrente = DateTime.ParseExact(data, "yyyy-MM", null).AddMonths(-1);
        contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
        return Partial("_PartialContas", contas);
    }

My HTML Components for those objects:

<th scope="row"><button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#CreateModal">Criar</button></th>
<br />
<div id="titleMonth">@Model.dataCorrente.ToString("MMMM", CultureInfo.CreateSpecificCulture("pt-br"))</div>
<br />
<button type="button" onclick="previousMonth()" class="btn btn-light">&larr;</button>
<input id="monthSelector" min="@(DateTime.Now.AddYears(-10).ToString("yyyy-MM"))" max="@(DateTime.Now.AddYears(10).ToString("yyyy-MM"))" onchange="changeDateSelector(this)" asp-for="dataCorrente" type="month">
<button type="button" onclick="nextMonth()" class="btn btn-light">&rarr;</button>

JS + JQuery (didn’t shows previousMonth method but its equal to the nextMonth) (the line with $(#monthSelector) was an attempt to save track of the value but didn’t work)):

<script>
    function changeDateSelector(date){
        var dataAtualizada = date.value;
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthSelector',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(dataAtualizada),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                $("#partial").html(data);
            }
        });
    }

    function nextMonth(){
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthNextButton',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($("#monthSelector").val()),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                console.log('@Model.dataCorrente.AddMonths(1).ToString("yyyy-MM")');
                $("#monthSelector").val('@Model.dataCorrente.AddMonths(1).ToString("yyyy-MM")');
                $("#partial").html(data);
            }
        });
    }

    function previousMonth(){
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthPrevButton',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($("#monthSelector").val()),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                console.log('@Model.dataCorrente.AddMonths(-1).ToString("yyyy-MM")');
                $("#monthSelector").val('@Model.dataCorrente.AddMonths(-1).ToString("yyyy-MM")');
                $("#partial").html(data);
            }
        });
    }
</script>

I Thought that when you bind a property the value automatically would change on the screen, so there’s my complete code for the view and the server-side:

@page
@using System.Globalization
@using ControleContas.Models.Contas
@model ControleContas.Pages.Contas.ContasViewModel
@{
}

<script>
    function changeDateSelector(date){
        var dataAtualizada = date.value;
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthSelector',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(dataAtualizada),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                $("#partial").html(data);
            }
        });
    }

    function nextMonth(){
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthNextButton',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($("#monthSelector").val()),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                console.log('@Model.dataCorrente.AddMonths(1).ToString("yyyy-MM")');
                $("#monthSelector").val('@Model.dataCorrente.AddMonths(1).ToString("yyyy-MM")');
                $("#partial").html(data);
            }
        });
    }

    function previousMonth(){
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthPrevButton',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($("#monthSelector").val()),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                console.log('@Model.dataCorrente.AddMonths(-1).ToString("yyyy-MM")');
                $("#monthSelector").val('@Model.dataCorrente.AddMonths(-1).ToString("yyyy-MM")');
                $("#partial").html(data);
            }
        });
    }
</script>

<div>
    <a class="nav-link text-dark" asp-area="" asp-page="/Contas/ContaCadastro"><button type="button" class="btn btn-primary">Cadastrar Cartão</button></a>
</div>

<th scope="row"><button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#CreateModal">Criar</button></th>
<br />
<div id="titleMonth">@Model.dataCorrente.ToString("MMMM", CultureInfo.CreateSpecificCulture("pt-br"))</div>
<br />
<button type="button" onclick="previousMonth()" class="btn btn-light">&larr;</button>
<input id="monthSelector" min="@(DateTime.Now.AddYears(-10).ToString("yyyy-MM"))" max="@(DateTime.Now.AddYears(10).ToString("yyyy-MM"))" onchange="changeDateSelector(this)" asp-for="dataCorrente" type="month">
<button type="button" onclick="nextMonth()" class="btn btn-light">&rarr;</button>

<!-- Modal -->
<div class="modal fade" id="CreateModal" tabindex="-1" role="dialog" aria-labelledby="CreateTitle" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content"> 
            <div class="modal-header">
                <h5 class="modal-title" id="CreateTitle">Criar Conta</h5>
                <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <form method="post">
                <div class="modal-body">
                    <input id="UserModal" hidden="hidden"></input>
                    <div class="form-group">
                        <label>Nome da Conta</label>
                        <input id="ValorCreateModal" asp-for="conta.Nome" type="text" class="form-control" placeholder="Nome" />
                    </div>
                    <div class="form-group">
                        <label>Valor</label>
                        <input id="ValorCreateModal" asp-for="conta.Valor" type="text" class="form-control" placeholder="Valor" />
                    </div>
                    <div class="form-group">
                        <label>Data</label>
                        <input id="DataCreateModal" asp-for="conta.Data" type="date" class="form-control" placeholder="Data da Conta" />
                    </div>
                    <div class="form-group">
                        <label>Prestações</label>
                        <input id="PrestacoesCreateModal" asp-for="conta.TotalPrestacoes" type="number" class="form-control" placeholder="Insira aqui a Quantidade de Prestações (1 - à Vista)" />
                    </div>
                    <div class="form-group">
                        <label>Pago?</label>
                        <input id="DespesaCreateModal" asp-for="conta.Pago" type="checkbox" class="form-control" />
                    </div>
                    <div class="form-group">
                        <label>Despesa?</label>
                        <input id="DespesaCreateModal" asp-for="conta.Despesa" type="checkbox" class="form-control" />
                    </div>
                    <!--
                        TODO: Criar um CheckBox para identificar se é uma conta para cartão, se for habilitar Selection para apresentar os cartões e assim vincular ele se não, vincular ao identity Logado.
                     <div class="form-group">
                        <label>Cartão?</label>
                        <input id="FimCartaoModal" type="text" class="form-control" placeholder="Fim Cartão" />
                    </div>-->
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                    <button type="submit" asp-page-handler="create" class="btn btn-primary">Save</button>
                </div>
            </form>
        </div>
    </div>
</div>

<div id="partial">    
  <partial name="_PartialContas" model=@Model.contas />
</div>

Server Side:

using ControleContas.DTO.Contas;
using ControleContas.Models.Contas;
using ControleContas.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;

namespace ControleContas.Pages.Contas
{
    public class ContasViewModel : PageModel
    {
        private readonly ContaDTO contaDTO;

        [BindProperty]
        public List<Conta> contas { get; set; }

        [BindProperty]
        public Conta conta { get; set; }

        [BindProperty]
        [DataType(DataType.Date)]
        public DateTime dataCorrente { get; set; }

        public ContasViewModel(IConfiguration config)
        {
            this.contaDTO = new ContaDTO(config);
        }

        #region Get Methods
        public void OnGet()
        {
            var now = DateTime.Now;
            var comecoMes = new DateTime(now.Year, now.Month, 1);

            dataCorrente = dataCorrente.Year == 1 ? comecoMes : dataCorrente;
            contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
        }
        #endregion

        #region Post Methods
        public IActionResult OnPostCreate()
        {
            conta.NomeUsuario = User.Identity.Name;
            contaDTO.CriaConta(conta);
            return Page();
        }

        public PartialViewResult OnPostMonthSelector([FromBody] string dataAtualizada)
        {
            dataCorrente = DateTime.ParseExact(dataAtualizada, "yyyy-MM", null);
            //contas = contaDTO.buscaContasUsuario(User.Identity.Name).Where(c => c.Data.Month == dataCorrente.Month && c.Data.Year == dataCorrente.Year).ToList();
            contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
            return Partial("_PartialContas", contas);
        }

        public PartialViewResult OnPostMonthNextButton([FromBody] string data)
        {
            dataCorrente = DateTime.ParseExact(data, "yyyy-MM", null).AddMonths(1);
            contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
            return Partial("_PartialContas", contas);
        }
        public PartialViewResult OnPostMonthPrevButton([FromBody] string data)
        {
            dataCorrente = DateTime.ParseExact(data, "yyyy-MM", null).AddMonths(-1);
            contas = BuscarContasUsuarioMes(User.Identity.Name, dataCorrente);
            return Partial("_PartialContas", contas);
        }
        #endregion

        #region Private Methods
        private List<Conta> BuscarContasUsuarioMes(string user, DateTime data)
        {
            return contaDTO.buscaContasUsuario(user).Where(c => c.Data.Month == dataCorrente.Month && c.Data.Year == dataCorrente.Year).ToList();
        }
        #endregion

    }
}

even added a label of the month to try to see changing, but it doesn’t:

enter image description here

enter image description here

Tryied to create some auxiliary variables on JS to save the data, bind the variable and a lot of things, but doesn’t work

Advertisement

Answer

My code was looking for a backend variable, I just needed to treat on the JS like below and now my arrows works.

<script>
    Date.prototype.yyyymm = function() {
        if (this.getMonth() + 1 < 10)
            return this.getFullYear() + '-' + '0'+(this.getMonth() + 1);
        else
            return this.getFullYear() + '-' + (this.getMonth() + 1);
    }

    function addMonths(date, months) {
        var d = date.getDate();
        date.setMonth(date.getMonth() + +months);
        if (date.getDate() != d) {
            date.setDate(0);
        }
        return date;
    }

    function changeDateSelector(date){
        var dataAtualizada = date.value;
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthSelector',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(dataAtualizada),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                $("#partial").html(data);
            }
        });
    }

    function nextMonth(){
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthNextButton',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($("#monthSelector").attr('value')),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                var stringData = ($("#monthSelector").val() + "-01").split("-");
                var date = new Date(stringData[1]+'-'+stringData[2]+'-'+stringData[0]);

                date = addMonths(date, 1);

                $("#monthSelector").attr('value',date.yyyymm());
                $("#partial").html(data);
            }
        });
    }

    function previousMonth(){
        $.ajax({
            type: "POST",
            url: '/Contas/ContaView?handler=MonthPrevButton',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($("#monthSelector").attr('value')),
            headers:
            {
                "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success:function(data){
                var stringData = ($("#monthSelector").val() + "-01").split("-");
                var date = new Date(stringData[1]+'-'+stringData[2]+'-'+stringData[0]);

                date = addMonths(date, -1);

                $("#monthSelector").attr('value',date.yyyymm());
                $("#partial").html(data);
            }
        });
    }
</script>
Advertisement