Build a dynamic form generator with Blazor

Alex Knijf
5 min readJul 15, 2020

--

Growing up to be a lazy programmer chick (picture usage: © Alex Knijf | 2020 )

My journey into Blazor started with the birth of my lovely daughter on 20–02–2020. The little dino-baby (one of her nicknames 😉) was eating, sleeping and being cute. As a new parent a lot of stuff is coming your way. You need to keep up with many things, especially the last time the baby had their milk. Looking at the apps that help you track these, any many other events, I had found that a lot require me to create an account and were sharing my data. Because don’t want to store that data somewhere other people could use it, I thought: let’s build my own.

This article is the first part of a series. You could read it to get the idea behind the Form generator. The second part of the series is a improvement of this Form generator so i would recommend read this and then go here.

Babysteps

Tracking your baby requires data, that data needs to be collected, and how do you collect that data?

Forms, forms, forms….

So we need forms. Let’s create a feeding session form in Blazor.

We’ll start with a model that represents a feeding session based on time.

Now let’s create a razor page that allows to fill these properties with values.

Working example found on BlazorFiddle here

A little growth jump

Having this form functional I wasn’t happy with all the necessary manual bootstrapping. The app will have a least 10 models that needed to be a form. The idea of creating and maintaining them wasn’t something I was looking forward to.

Fortunately In Angular I’ve created multiple form generators so it was time to explore the dynamic way. The idea is to generate forms based on POCO’s and data-annotations. This should result in dynamic forms. Having the experience with the built-in EditForm I wanted to leverage as much of the out-of-box behaviour, because there is no need to reinvent the wheel.

Requirements

  • Must work with EditForm
  • So we can use the built-in validation and form handling logic
  • Must be based on InputBase
  • So the EditForm is able to use it’s built-in validation and change handling logic
  • CustomFormElements Must be bind-able
  • The form fields that are custom implemented like a datepicker should be able to use the bind-Value syntax
  • CustomFormElements Must have input validation
  • The input validation should be extendable from the InputBase
  • Must be generated by a POCO
  • The form must use reflection to list all properties and it’s decorators to render them as form fields
  • Should be extendable with custom components
  • The form should have a repository that contains a mapping to a component that should be used as form element in the form when a property is of a specific Type
  • Should be easy to change CSS framework
  • The form should be able to switch, for example, to: Bootstrap or Material Design

Implementation of Dynamic Forms

The intend is that I lay down the basic groundwork for a fully featured dynamic form generator. So don’t expect a fully grown baby yet 😉.

Now that is out of the way let’s start by creating a new folder and component.

  1. Navigate to project root of you Blazor application
  2. Create the folders Components\FormGenerator
  3. Create a new FormGenerator.razor file

4. Create a new FormGenerator.razor.cs file
(Make sure it’s in the same place as the .razor file)

5. We will need to have a loader component, so let create a new file FormElement.razor

6. Let’s create the backend file FormGenerator.razor.cs
(Make sure it’s in the same place as the .razor file)

7. Now let’s create a component mapping, we use the Type of the property to show a corresponding HTML Element represented by a component.

8. Create in the FormGenerator folder a new file FormGeneratorComponentsRepository.cs

Let’s setup the mapping for the dynamic form, open Startup.cs and register the component mapping repo as a singleton to the Dependency Injection system.

This will, for example, render properties of type: String as a Blazor InputText component

Let’s use it

Running this application will result in a un-styled rendered dynamic form generated by a POCO!!! Unfortunately the the InputSelect is not rendering the KindOfFood enum as the possible options for the select element.

This is because InputSelect expects <option> elements as it's child. So we need to append children dynamically to the InputSelect component.

Append the children

There are multiple ways to create an architecture for this. I’ve chosen the following architecture that results in a simple and scoped solution:

  • Leaving the FormGeneratorComponentsRepository unchanged
  • Adding a interface called IRenderChildren
  • Extend the FormElement to check for the IRenderChildren interface
  • Extend the FormElement to execute the renderChildren methods with the correct parameters

Let’s add the support for rendering children:

  1. Create a new file in FormGenerator folder called: IRenderChildren.cs

2. Create a new file in FormGenerator folder called: InputSelectOption.razor. This will be the option HTML element.

3. Now let’s use this component to render it in the InputSelect component

4. Create a new file in FormGenerator folder called: RenderChildrenInputSelect.cs

Extending the default InputSelect component

The last thing is to set it up in the dynamic Form component mapping in the startup.cs The mapping is done as a string because it could be used in a different way than Type to Type mapping.

Run the application and you should now have a generated form based on the POCO with working selection element! 🎉✨

Jeeej it’s working!

working example is found here: https://github.com/Aaltuj/BlazorFormGeneratorDemo

Now we need to add styling…. unfortunately this article is getting too long if we handle that part as well. This is just a proof of concept, I would like to make some improvements to make it more production ready:

  • Move to separate project
  • Implement the styling for frameworks like Bootstrap or your own CSS styling
  • ValidationMessage in the element
  • Translatable ValidationMessage
  • Pass-through of the EditForm events

This article is the first part of a series. Thank you for reading till here, the second part of the series is a improvement of this Form generator so i would recommend to go here. Any feedback is welcome

--

--

Alex Knijf

Senior Front-end Developer working with TypeScript, JavaScript, .NET (Core) WebApi and DB stuff on Digital Tables, Mobile and Desktop living in the Netherlands