Learn ASP.NET Core 3.1 with mini project : MVC, Razor Pages, Web API, Entity Framework Core, and Blazor. Hands-on online training course starting in August 2020. Click here to know more.

Create Simple DatePicker Component in Blazor

ASP.NET Core Blazor allows you to develop client side web applications using HTML, Razpr, and C#. A typical Blazor application consists of one or more Razor components. A Razor component physically exists as .razor file and contains a mix of HTML markup, Razor constructs, and C# code. A Razor component can either be used as if it is a page or it can be housed inside other component. If you are beginner in Blazor it's worthwhile to learn some fundaments of building Blazor components. That's what this article is about.

In this article you will develop a simple Razor component called DatePicker. We won't be developing a fancy, feature rich popup DatePicker, we will rather build a simple one as shown below, and focus more on learning the basics of component development in Blazor. Although most of the modern browsers support HTML5 DatePicker user interface, this simple DatePicker will help you understand basics such as creating components, using components, setting component properties, handling events, and two-way data binding.

This is how our DatePicker is going to look like:

Ok. Let's get going.

Begin by creating a new Blazor Server app using Visual Studio.

And then pick Blazor Server project template.

Once the application is created, add Components folder under Shared. Then add a new Razor component named DatePicker to it. You can do that using Add New Item dialog shown below.

Components that are intended to be used as pages reside under Pages folder whereas components intended to be used by other components or pages can be kept in any folder. In this case we keep DatePicker component in Shared > Components folder.

Next, open DatePicker.razor file in Visual Studio and the following code to its @code block.

@code {
    public int Day { get; set; }
    public int Month { get; set; }
    public int Year { get; set; }

    public string[] Months { get; set; } = { 
       "January", "February", "March", 
       "April", "May", "June", "July", 
       "August", "September", "October", 
       "November", "December" };
}

The @code block holds the code required by the component. It could be properties, member variables, or methods. In this case we declare four properties namely Day, Month, Year, and Month. The Month property holds an array of month names. These properties are used in the component's markup. So, add the following markup below the @code block.

<select @bind="Day">
    @for (int i = 1; i <= 31; i++)
    {
        <option>@i</option>
    }
</select>
<select @bind="Month">
    @for (int i = 1; i <= 12; i++)
    {
        <option value="@i">@Months[i-1]</option>
    }
</select>
<select @bind="Year">
    @for (int i = DateTime.Now.Year-5; 
i <= DateTime.Now.Year + 5; i++)
    {
        <option>@i</option>
    }
</select>
<button type="button">Select</button>

The above markup consists of three <select> elements for displaying day, month, and year respectively. There is also a button to indicate that a date has been selected. Notice how Day, Month, and Year properties are used in the markup using @bind syntax. Using @bind as shown here ensures that the value of Day / Month / Year is assigned to the value DOM property of the respective <select> element. While filling the month dropdown list we display month names but assign month number as an <option> value. While filling the year dropdown list, 10 years are filled - five before the current year and five after the current year.

Save DatePicker.razor file. You will visit this file again later while adding more functionality.

Now, add another Razor component named DatePickerHost.razor inside the Pages folder. This component is intended to house the DatePicker component. Open DatePickerHost.razor and add @page directive at the top:

@page "/datepickerhost"

The @page directive indicates that this Razor component is to be used as a page. The @page directive also specifies a route where the page will be accessible - /datepickerhost.

Then open _Imports.razor file and add the following namespace entry there:

@using BlazorComponentDemo.Shared.Components

We need this entry because our DatePicker component resides in the above namespace. Adding this entry will make it accessible to the DatePickerHost.

Then place the DatePicker component in the DatePickerHost as shown below:

<DatePicker></DatePicker>

As you can see, you used the DatePicker component as it it is markup element.

Run the application, go to the browser's address bar and navigate to /datepickerhost. This will display the DatePicker as shown below.

As you can see the DatePicker is empty when displayed in the browser. Let's fix this by showing current date in it by default.

Go to DatePicker.component and add this code:

protected override void OnInitialized()
{
    Day = DateTime.Now.Day;
    Month = DateTime.Now.Month;
    Year = DateTime.Now.Year;
}

Here, you are overriding OnInitialized() method. This method indicates that the component has been initialized and can be used to perform some initialization tasks. Here we assign certain default values to the Day, Month, and Year properties.

If you run the application again this time it will show current date in the DatePicker.

Now we are able to display current date in the DatePicker. But wouldn't it be nice if the DatePickerHost is also allowed to specify a default date to be displayed? Let's add that functionality.

Go to DatePicker component and add a public property named InitialDate as shown below:

[Parameter]
public DateTime InitialDate { get; set; }

Notice that the InitialDate property is decorated with [Parameter] attribute. The [Parameter] attribute marks the property to be the component's parameter - something that can be set from the external world.

Also add the following code in the OnInitialized() method:

protected override void OnInitialized()
{
    Day = InitialDate.Day;
    Month = InitialDate.Month;
    Year = InitialDate.Year;
}

Now, go to DatePickerHost component and add a property there called DefaultDate.

 public DateTime DefaultDate { get; set; }

And assign some date to this property in DatePickerHost's OnInitialized() method.

protected override void OnInitialized()
{
    DefaultDate = new DateTime(2019, 9, 2);
}

Finally, set the DatePicker components InitialDate parameter like this:

<DatePicker InitialDate="DefaultDate"></DatePicker>

If you run the application you will get this output. 

So far so good. Currently even if you select some values in the three dropdown lists and hit the Select button, nothing special happens. When a user clicks on the Select button, we would like to notify the parent (DatePickerHost) about the changed date. This way the parent component can read the DatePicker value and take some action on that. This calls for raising an event from the DatePicker and handling it in the DatePickerHost.

Let's add that piece of functionality.

Go to DatePicker component and are an event as shown below:

[Parameter]
    public EventCallback<DateTime> DateSelected 
{ get; set; }

Here, you defined an event callback named DateSelected. This callback will supply the selected DateTime to the event handler function. This is just event declaration. You need to raise this event when the Select button is clicked. To do so add the following method in the @code block of DatePicker.

public Task OnSelectClick()
{
    DateTime dt = new DateTime(Year, Month, Day);
    return DateSelected.InvokeAsync(dt);
}

This code grabs the day, month, and year selected in the three dropdown lists and gets the DateTime value. It then raises the DateSelected event by calling InvokeAsync() and by passing the DateTime to it. Note that OnSelectClick() method returns a Task since InvokeAsync() is an asynchronous operation.

The OnSelectClick() should get called when a user clicks on the Select button. You can wire it to the click event of the button like this:

<button type="button" 
@onclick="OnSelectClick">Select</button>

As you can see, @onclick syntax wires OnSelectClick() method to be the click event handler of the button.

Next, you need to handle the DateSelected event of the DatePicker component in DatePickerHost. So, go to DatePickerHost and modify the DatePicker markup like this:

<DatePicker 
    InitialDate="DefaultDate"
    DateSelected="OnDateSelected">
</DatePicker>

The above markup specifies that the DateSelected event of the DatePicker will be handled by OnDateSelected() method written inside DatePickerHost. The OnDateSelected() method is shown below:

public void OnDateSelected(DateTime dt)
{
    SelectedDate = dt;
}

The OnDateSelected() event handler receives the DateTime selected in the DatePicker. Inside, it assigns the DateTime to SelectedDate property so that it can be used for further processing. The SelectedDate property of DatePickerHost looks like this:

public DateTime SelectedDate { get; set; }

For the sake of testing we will output the value of SelectedDate in DatePickerHost by adding this markup:

<h3>Selected Date : @SelectedDate</h3>

Run the application, select some values in the three dropdown lists, and hit the Select button. You should see the selected date rendered below the DatePicker.

In the preceding example, you are able to set the initial date in the DatePicker and also get notified when date selection changes. What if we want to have two-way data binding? By two-way data binding it means that changes to the selected date are propagated from DatePickerHost to DatePicker and vice a versa.

Open DatePicker component and add one more  parameter property called SelectedDate.

[Parameter]
public DateTime SelectedDate
{
    get {
        return new DateTime
(Year, Month, Day);
    }
    set {
        Day = value.Day;
        Month = value.Month;
        Year = value.Year;
    }
}

Notice the code in set block. It simply assigns the Day, Month, and Year properties to the respective parts of the specified DateTime.

Also add one more event to DatePicker called SelectedDateChanged

[Parameter]
public EventCallback<DateTime> 
SelectedDateChanged { get; set; }

Then change the OnSelectClick() method as shown below:

public Task OnSelectClick()
{
    SelectedDate = new DateTime
(Year, Month, Day);
    return SelectedDateChanged.
InvokeAsync(SelectedDate);
}

This code should look familiar to you since you used it before. The only difference here is that you raise SelectedDateChanged event.

Now, open DatePickerHost and assign the SelectedDate property in the OnInitialized() method.

protected override void OnInitialized()
{
    SelectedDate = DateTime.Now;
}

The SelectedDate property will be data bound with DatePicker so that any changes to it will be reflected in the DatePicker component. For example, after setting current date to SelectedDate property as shown above the DatePicker dropdown lists will reflect this date value.

To confirm that any change to SelectedDate is propagated to the DatePicker add a button at the end of DatePickerHost like this:

<button type="button" 
@onclick="OnSetDateClick">Set Date</button>

The Set Date button when clicked simply changes the value of SelectedDate property. The OnSetDateClick() event handler looks like this:

public void OnSetDateClick()
{
    SelectedDate = new DateTime(2019, 11, 2);
}

Here, the code simply sets some different date to the SelectedDate property.

Now, modify the <DatePicker> markup as shown below:

<DatePicker @bind-SelectedDate="@SelectedDate">
</DatePicker>

Notice the code shown in bold letters. It performs two-way data binding between SelectedDate property of DatePicker and SelectedDate property of DatePickerHost.

Run the application and observe the output. The following figure shows the initial run of the application.

Notice that the dropdown lists reflect the date assigned to DatePickerHost's SelectedDate property.

Then change the date selection in the dropdown lists and click on the Select button. You will find that the message correctly displays the newly selected date.

This proves that any change to DatePicker's SelectedDate property is reflected in DatePickerHost's SelectedDate property.

Now, click on the Set Date button that sets DatePickerHost's SelectedDate property to a new value. After doing that, the dropdown lists should reflect the changed date.

Thus any changes to the SelectedDate properties are synchronized between the DatePicker and DatePickerHost.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant, trainer, author, yoga mentor, and meditation teacher. He has been programming, meditating, and teaching for 24+ years. He conducts instructor-led online training courses in ASP.NET family of technologies for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Facebook  Twitter  LinkedIn  YouTube

Posted On : 16 March 2020


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates