Forum Discussion

najeeb-anwari's avatar
najeeb-anwari
Copper Contributor
Oct 17, 2022
Solved

Could not set or bind model property with Bootstrap Datepicker in Blazor

I am using bootstrap datepicker and the problem is that when I pick a date, it does not fire a change or input event and noting is binding with the model property Course.StartDate or Course.EndDate. The default datepicker works but does not support Afghanistan datetime. That is why I use boostrap datepicker.

Blazor code:

 

@using Microsoft.AspNetCore.Mvc.Rendering
@using myproject.Data
@using Microsoft.JSInterop;
@inject myproject.Repository.CoursesRepository _coursesRepository

@inject IJSRuntime JS

<EditForm Model="@Course" OnValidSubmit="e=> { if(selectedId == 0) { addCourse(); } else { updateCourse(Course.CourseId); } }">
<div class="mb-2">
    <div>@Course.StartDate</div>
    <label class="col-form-label" for="StartDate">@Loc["Start Date"]<span class="text-danger fs--1">*</span>:</label>
    <InputDate class="form-control" @bind-Value="Course.StartDate" @bind-Value:format="yyyy-MM-dd" id="StartDate" />
    <ValidationMessage class="text-danger" For="(() => Course.StartDate)"/>
</div>

<div class="mb-2">
    <label class="col-form-label" for="EndDate">@Loc["End Date"]<span class="text-danger fs--1">*</span>:</label>
    <InputDate class="form-control" @bind-Value="Course.EndDate" @bind-Value:format="yyyy-MM-dd" id="EndDate"/>
    <ValidationMessage class="text-danger" For="(() => Course.EndDate)"/>
</div>
</EditForm>
@code {

  public CourseModel Course = new();
  public string[] dates = new string[] { "#StartDate", "#EndDate" };
    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);
        loadScripts();
    }

    void addCourse()
    {
        _coursesRepository.AddCourse(Course);
        FillData();
        Course = new();
        var title = "Course";
        Swal.Success(title : Loc[$"{title} added successfully"],toast : true);

    }
    // initializes the datepicker
    public async Task loadScripts()
    {
        await JS.InvokeVoidAsync("initializeDatepicker", (object) dates);
    }

}

 

This is script for initializing the datepickers

 

<script>
    function initializeDatepicker(dates) {
        dates.forEach((element) => {
                $(element).datepicker({
                onSelect: function(dateText) {
                    // this is not working
                    element.value = this.value;
                    /* 
                      tried this and still not working
                      $(element).trigger("change");
                      also tried this and still not working
                      $(element).change();
                    */
                    // this is working
                    console.log("Selected date: " + dateText + "; input's current value: " + this.value);
                },
                dateFormat: 'yy-mm-dd',
                changeMonth: true,
                changeYear: true

            });
        });
           
    }
</script>

 

 

    • najeeb-anwari's avatar
      najeeb-anwari
      Copper Contributor

      yashints 

      Thanks for your help! I have been looking for a solution and this was the one that worked for me.

      @using Microsoft.AspNetCore.Mvc.Rendering
      @using myproject.Data
      @using Microsoft.JSInterop;
      @inject myproject.Repository.CoursesRepository _coursesRepository
      
      @inject IJSRuntime JS
      
      <EditForm Model="@Course" OnValidSubmit="e=> { if(selectedId == 0) { addCourse(); } else { updateCourse(Course.CourseId); } }">
      <div class="mb-2">
          <div>@Course.StartDate</div>
          <label class="col-form-label" for="StartDate">@Loc["Start Date"]<span class="text-danger fs--1">*</span>:</label>
          @*changed this line->*@
          <input class="form-control" @bind-value="Course.StartDate" @bind-value:format="yyyy-MM-dd" @bind-value:event="oninput"  id="StartDate"  @onchange="@( (ChangeEventArgs args) => { Course.StartDate =  DateTime.Parse(args.Value.ToString()); })"/>
          <ValidationMessage class="text-danger" For="(() => Course.StartDate)"/>
      </div>
      
      <div class="mb-2">
          <label class="col-form-label" for="EndDate">@Loc["End Date"]<span class="text-danger fs--1">*</span>:</label>
          @*changed this line->*@
          <input class="form-control" @bind-value="Course.EndDate" @bind-value:format="yyyy-MM-dd" @bind-value:event="oninput" id="EndDate" @onchange="@( (ChangeEventArgs args) => { Course.EndDate =  DateTime.Parse(args.Value.ToString()); })"/>
          <ValidationMessage class="text-danger" For="(() => Course.EndDate)"/>
      </div>
      </EditForm>
      @code {
      
        public CourseModel Course = new();
        public string[] dates = new string[] { "#StartDate", "#EndDate" };
          protected override void OnAfterRender(bool firstRender)
          {
              base.OnAfterRender(firstRender);
              loadScripts();
          }
      
          void addCourse()
          {
              _coursesRepository.AddCourse(Course);
              FillData();
              Course = new();
              var title = "Course";
              Swal.Success(title : Loc[$"{title} added successfully"],toast : true);
      
          }
          // initializes the datepicker
          public async Task loadScripts()
          {
              await JS.InvokeVoidAsync("initializeDatepicker", (object) dates);
          }
      
      }

      I changed the script like this.

      <script>
              function initializeDatepicker(dates) {
                  dates.forEach((element) => {
                       $(element).datepicker({
                          onSelect: function(dateText) {
                              // changed it like this
                              var myElement = $(this)[0];
                              var event = new Event('change');
                              myElement.dispatchEvent(event);
                          },
                          dateFormat: 'yy-mm-dd',
                          changeMonth: true,
                          changeYear: true
      
                      });
                  });
                 
              }
          </script>

      But if we change the datepicker to a component, it will be better.

Resources