mediabuff / Whyvra.Blazor.Forms

A dynamic form builder that binds to your model classes and creates the corresponding HTML form for you.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Whyvra.Blazor.Forms

NuGet Package NuGet Package Download Count LICENSE PRs Welcome

A dynamic form builder that binds to your model classes and creates the corresponding HTML form for you.

IMPORTANT : Please note that version 1.0.0 introduces breaking changes. Whyvra.Blazor.Forms is now a base package used to implement dynamic form builders. It exposes specific interfaces and base classes for builders and components to handle things like data binding and validation. For the Bulma implementation, please see Whyvra.Blazor.Forms.Bulma.

Introduction

This package allows for the creation of dynamic forms with a class implementing IFormBuilder<TModel>. It relies on a IFormModel<TModel> that is created by calling the Build() method on the form builder. The form model can then be passed to a WhyvraForm or a component implementing WhyvraFormBase which will output the HTML markup for your form.

This package can be used to create implementations for different frameworks. However, given the current state of Blazor and how most frameworks depend on JavaScript, only an implementation for the Bulma framework has been created.

Bulma is a CSS-only framework that does not require any external JavaScript. For this reason, it integrates well with Blazor. For the Bulma implementation, please see Whyvra.Blazor.Forms.Bulma.

Installation

You should really only install this package if you're creating an implementation of Whyvra.Blazor.Forms for a specific framework.

Install the package by running the following command:

dotnet add package Whyvra.Blazor.Forms

Usage

In order to create a framework-specific implementation of Whyvra.Blazor.Forms, you must create a class that implements IFormBuilder<TModel> and create components for the corresponding methods like Input, FileInput, Number, etc.

Form builder

This package provides an abstract class FormBuilder<TModel> that implements some methods of the IFormBuilder<TModel> interface. The base class is meant to handle component registration and some basic methods. You must wire methods like Input to add your own component using the Component method.

It is strongly suggested that your components inherit from WhyvraComponentBase which exposes convenient methods for data binding and handle validation if required.

Let's have a look at the code below:

using Whyvra.Blazor.Forms.Builders;
using Whyvra.Blazor.Forms.Components;

namespace Whyvra.Blazor.Forms.MyFramework
{
    public class MyFrameworkFormBuilder<TModel> : FormBuilder<TModel>
    {
        public override IFormBuilder<TModel> Input<TProperty>(Expression<Func<TModel, TProperty>> lambda)
        {
            // Add component
            Component<MyFrameworkInput<TModel>, TProperty>(lambda);

            // Get the field's display name and set as placeholder
            var name = CurrentComponent.Parameters["DisplayName"] as string;
            CurrentComponent.Parameters["Placeholder"] = name;

            return this;
        }
    }
}

This example provides an implementation for the Input method.

The Component method is used to register the MyFrameworkInput<TModel> component.

Values inherited from WhyvraComponentBase are set in the Component method. The DisplayName parameter is retrieved and set on the Placeholder parameter, which is specific to this component in this example.

Custom component

You can create your own custom components and add them using the Component method.

WhyvraComponentBase provides a set of standard properties like DisplayName, InternalName, IsVisible, etc. It also provides methods for data binding and validation.

Here's an example below:

@typeparam TModel
@inherits WhyvraComponentBase<TModel>

<div class="field">
    <label for="@InternalName">@DisplayName</label>
    <p class="control">
        <input type="text" id="@InternalName" class="input @(FormState == FormState.Read ? "is-static" : "")"
            placeholder="@Placeholder" value="@(GetData(FormModel.DataModel))" 
            readonly="@(FormState == FormState.Read)"
            @onchange="HandleChange"
            @onfocusout="HandleValidation" />
        @if (ValidationMessages.Any())
        {
            <p class="help is-danger">@ValidationMessages.First()</p>
        }
    </p>
</div>

@code
{
    private void HandleChange(ChangeEventArgs e)
    {
        var value = e.Value.ToString();
        SetData(FormModel.DataModel, value);
    }

    private void HandleValidation()
    {
        if (GetValidationResult == null) return;

        var result = GetValidationResult();
        ValidationMessages = result.ValidationMessages.ContainsKey(ValidationPath)
            ? result.ValidationMessages[ValidationPath]
            : Enumerable.Empty<string>();
    }
}

This custom component uses GetData, SetData and FormModel to retrieve and set data on the model class. It also uses the GetValidationResult and ValidationMessages properties to retrieve validation messages for the current state of the model class.

License

Released under the MIT License.

About

A dynamic form builder that binds to your model classes and creates the corresponding HTML form for you.

License:MIT License


Languages

Language:C# 93.3%Language:HTML 6.7%