Blog Barista: Anthony Wolf | Sept 4, 2019 | Web Development | Brew time: 5 min

Blazor is Microsoft’s latest web-development framework which is currently included as part of the ASP.NET Core preview. Microsoft recently announced that Blazor is officially in preview which means it is no longer experimental. This also means that active development will continue on the framework and support will begin once it is fully released. While it is no longer experimental, it is important to realize that Blazor is still not production-ready, hence the “preview” label.

Previously, I’ve written about Blazor in another blog post for KL&A. In A Tour of Blazor, I covered many different topics and explored the different things you can do with Blazor. One thing about Blazor which I felt was a bit clunkier than I wanted was the forms and validation. In this post, I’m going to discuss the EditForm component (Microsoft.AspNetCore.Components.Forms) as well as various input and validation related components. After reading this post, I think you will agree that my previous attempt at writing forms in Blazor wasn’t quite right and this new way is much better.

Back End

To start, I created an ASP.NET Core Hosted Blazor project in .NET Core 3 Preview 7 using Visual Studio 2019 Preview. The first thing I noticed was that all of the “.cshtml” files I was familiar with from the asp.net core hosted Blazor template back when I wrote “A Tour of Blazor” now had a new extension: “.razor.” This change is noted in the news article announcing Blazor’s official preview (which is linked above).

Just like before, I separated the markup from the code using the @inherits directive in all existing pages and components. Then, I set out to implement a simple create form based on the existing pages in the project template. Being a full-stack developer with a back-end preference, I began with my API code. I rewrote the “WeatherForecastController” to no longer randomly generate forecasts, but to instead get the data from a .json file, and also added a post action.

WeatherForecastController.cs

Shared Code

At this point, some readers may be raising their eyebrows at the notion of a simple .json file being my database, but keep in mind, this isn’t production code and it is only meant to be a simple example. Also, the focus of this blog post is about forms and validation in client-side Blazor rather than CRUD in general. For the validation logic, I simply augmented the existing “WeatherForecast” with framework data annotations (System.ComponentModel.DataAnnotations) in addition to a custom validation attribute.

WeatherForecast.cs

MinDateForSummaryAttribute.cs

The plain-English arbitrary validation logic is as follows: the TemperatureC property is required, and the Date property must be between January 1st, 1753 and January 1st, 3000, the Summary property must be less than 25 characters; and it must also be blank for any date before the year 1900. This is an example of cross-property validation. 

Note: Since “Date” is not a nullable DateTime, clearing the date control just sets it to DateTime.MinValue. 

Front End

With the back-end complete, I added a create button to the “fetchdata” page which will take us to a new page called “BlazorForms.”

FetchDataCode.cs

FetchData.razor

BlazorFormsCode.cs

BlazorForms.razor

The following components are part of the “Microsoft.AspNetCore.Components.Forms” namespace: EditForm, DataAnnotationsValidator, and ValidationMessage. 

Note: Usage of EditForm’s EditContext parameter instead of simply using the Model parameter. 

This is required to implement cross-control validation, and you’ll find most examples on the internet simply by using the Model parameter without bothering to explore the EditContext. As you can see, I subscribe to the EditContext’s OnFieldChanged event with a handler. By doing this, it makes sure whenever a weather forecast has a date before the year 1900 that any non-null/whitespace values in the Summary field is invalid. This is accomplished by telling the EditContext that the Summary field has changed whenever the Date field changes. Obviously, the Summary field hasn’t actually changed, but issuing this notification causes the control to be re-validated which is what we want in this case.

Now, you may notice, or at least be aware, that I am not using the built-in out-of-the-box input components such as InputDate, InputText, and InputNumber. This is because these default-to-firing values change events only during the “onchange” event, which only occurs when the control loses focus. I wanted validation to occur as the user types, so these overrides were necessary. For simple types like InputText and InputNumber, I was able to derive directly from those types and no additional code-behind was necessary. As you’ll see, KlaInputDate was a bit more complicated; I had difficulty getting the oninput binding correctly to parse and update the current value without adding in a custom code-behind instead of directly inheriting InputDate<DateTime>.

KlaInputDateCode.cs

KlaInputDate.razor

KlaInputNumber.razor

KlaInputText.razor

The extra complexity of the KlaInputDate component is a result of these base components not exactly eating the same dog food as developers who write code using Blazor. If you’re curious as to what the source code for the built-in components looks like, I strongly encourage you to head on over to the ASP.NET Core GitHub repository and poke around: https://github.com/aspnet/AspNetCore. Doing so can be very illuminating when you’re trying to work within the framework and get behavior outside the norm of using provided components as-is. Specifically, I recommend exploring InputText.cs, InputDate.cs, InputNumber.cs, InputBase.cs, EditContext.cs, and EditForm.cs. Check out the video below to see this Blazor application in action!

If you have a simpler implementation for KlaInputDate, I strongly encourage you to post a link to your GitHub gist in the comments below!

0 Comments

Other recent posts:

Team Building in a Remote Environment

Team Building in a Remote Environment

Blog Barista: Dana Graham | June 15th, 2022 | Culture | Brew time: 5 min
Let me start by saying I don’t care for the term “work family.” I have a family I love, and they have absolutely nothing to do with my career. I want my work life to be its own entity. I like boundaries (and the George Costanza Worlds Theory). Certainly, I want to enjoy and trust my coworkers, and I want to feel supported and cared for…

read more

Pin It on Pinterest