SOLVED

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

Copper Contributor

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>

 

 

2 Replies
best response confirmed by najeeb-anwari (Copper Contributor)
Solution
Hi Najeeb,

I think you're missing the `onchange` event, take a look at this example which gives you an idea on how to proceed:

https://www.codeproject.com/Tips/5290232/Blazor-datepicker-Component-using-JQuery

That example is not using the bootstrap datepicker but the concept is the same

@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.

1 best response

Accepted Solutions
best response confirmed by najeeb-anwari (Copper Contributor)
Solution
Hi Najeeb,

I think you're missing the `onchange` event, take a look at this example which gives you an idea on how to proceed:

https://www.codeproject.com/Tips/5290232/Blazor-datepicker-Component-using-JQuery

That example is not using the bootstrap datepicker but the concept is the same

View solution in original post