Bootstrap Blazor 实战动态表单组件

1.新建工程

源码

新建工程b18ValidateForm,使用 nuget.org 进行 BootstrapBlazor 组件安装, Chart 库,字体. 将项目添加到解决方案中

dotnet new blazorserver -o b18ValidateForm
dotnet add b06chart package BootstrapBlazor
dotnet add b06chart package BootstrapBlazor.FontAwesome
dotnet sln add b18ValidateForm/b18ValidateForm.csproj

2.样式表和Javascript 引用

增加主题样式表到 Pages/_Layout.cshtml 文件中

删除

并在下面添加三行



添加 Javascript 引用到 Pages/_Layout.cshtml 文件中

之前添加


3.添加增加命名空间引用到 _Imports.razor 文件中

@using BootstrapBlazor.Components

4.增加 BootstrapBlazorRoot 组件到 App.razor 文件中


    
        ...
    

5.添加BootstrapBlazor服务到 Program.cs 文件中

builder.Services.AddSingleton(); 后加入

builder.Services.AddBootstrapBlazor();

6.添加EditorForm测试代码

Index.razor


    
        
        
        
    
    
        

Index.razor.cs

using BootstrapBlazor.Components;
using Microsoft.Extensions.Localization;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;

namespace b18ValidateForm.Pages;

public sealed partial class Index
{
    [NotNull]
    private Foo? Model { get; set; }

    /// 
    /// 
    /// 
    protected override void OnInitialized()
    {
        Model = new Foo()
        {
            Name = "",
            Count = 1,
            Address = "TestAddress",
            DateTime = new DateTime(1997, 12, 05),
            Education = EnumEducation.Middle
        };
    }

}
Demo示例数据
/// 
/// Demo示例数据
/// Demo sample data
/// 
public class Foo
{
    // 列头信息支持 Display DisplayName 两种标签

    /// 
    ///
    /// 
    [Display(Name = "主键")]
    [AutoGenerateColumn(Ignore = true)]
    public int Id { get; set; }

    /// 
    ///
    /// 
    [Required(ErrorMessage = "{0}不能为空")]
    [AutoGenerateColumn(Order = 10, Filterable = true, Searchable = true)]
    [Display(Name = "姓名")]
    public string? Name { get; set; }

    /// 
    ///
    /// 
    [AutoGenerateColumn(Order = 1, FormatString = "yyyy-MM-dd", Width = 180)]
    [Display(Name = "日期")]
    public DateTime? DateTime { get; set; }

    /// 
    ///
    /// 
    [Display(Name = "地址")]
    [Required(ErrorMessage = "{0}不能为空")]
    [AutoGenerateColumn(Order = 20, Filterable = true, Searchable = true)]
    public string? Address { get; set; }

    /// 
    ///
    /// 
    [Display(Name = "数量")]
    [Required]
    [AutoGenerateColumn(Order = 40, Sortable = true)]
    public int Count { get; set; }

    /// 
    ///
    /// 
    [Display(Name = "是/否")]
    [AutoGenerateColumn(Order = 50)]
    public bool Complete { get; set; }

    /// 
    ///
    /// 
    [Required(ErrorMessage = "请选择学历")]
    [Display(Name = "学历")]
    [AutoGenerateColumn(Order = 60)]
    public EnumEducation? Education { get; set; }

    /// 
    ///
    /// 
    [Required(ErrorMessage = "请选择一种{0}")]
    [Display(Name = "爱好")]
    [AutoGenerateColumn(Order = 70, Editable = false)]
    public IEnumerable Hobby { get; set; } = new List();

    #region Static methods
    /// 
    /// 
    /// 
    protected static readonly Random Random = new();

    /// 
    /// 生成Foo类,随机数据
    /// Generate Foo class, random data
    /// 
    /// 
    /// 
    public static Foo Generate(IStringLocalizer localizer) => new()
    {
        Id = 1,
        Name = localizer["Foo.Name", "1000"],
        DateTime = System.DateTime.Now,
        Address = localizer["Foo.Address", $"{Random.Next(1000, 2000)}"],
        Count = Random.Next(1, 100),
        Complete = Random.Next(1, 100) > 50,
        Education = Random.Next(1, 100) > 50 ? EnumEducation.Primary : EnumEducation.Middle
    };

    /// 
    /// 生成 Foo 类,随机数据
    /// Generate Foo class, random data
    /// 
    /// 返回一个Foo类的List,Return a List of Foo class
    public static List GenerateFoo(int count = 80) => Enumerable.Range(1, count).Select(i => new Foo()
    {
        Id = i,
        Name = "Foo.Name"+ $"{i:d4}",
        DateTime = System.DateTime.Now.AddDays(i - 1),
        Address = "Foo.Address"+$"{Random.Next(1000, 2000)}",
        Count = Random.Next(1, 100),
        Complete = Random.Next(1, 100) > 50,
        Education = Random.Next(1, 100) > 50 ? EnumEducation.Primary : EnumEducation.Middle
    }).ToList();

  
    /// 
    /// 通过 Count 获得颜色
    /// 
    /// 
    /// 
    public static Color GetProgressColor(int count) => count switch
    {
        >= 0 and < 10 => Color.Secondary,
        >= 10 and < 20 => Color.Danger,
        >= 20 and < 40 => Color.Warning,
        >= 40 and < 50 => Color.Info,
        >= 50 and < 70 => Color.Primary,
        _ => Color.Success
    };

    /// 
    /// 通过 Id 获取 Title
    /// 
    /// 
    private static string GetTitle() => Random.Next(1, 80) switch
    {
        >= 1 and < 10 => "Clerk",
        >= 10 and < 50 => "Engineer",
        >= 50 and < 60 => "Manager",
        >= 60 and < 70 => "Chief",
        _ => "General Manager"
    };

    /// 
    /// 
    /// 
    /// 
    /// 
    public static string GetTitle(int id) => Cache.GetOrAdd(id, key => GetTitle());

    /// 
    /// 
    /// 
    /// 
    public static Func, string, SortOrder, IEnumerable> GetNameSortFunc() => Utility.GetSortFunc();

    private static ConcurrentDictionary Cache { get; } = new();
    #endregion
}

/// 
///
/// 
public enum EnumEducation
{
    /// 
    ///
    /// 
    [Display(Name = "小学")]
    Primary,

    /// 
    ///
    /// 
    [Display(Name = "中学")]
    Middle
}

7.运行

Bootstrap Blazor 实战动态表单组件_第1张图片

8.新需求: 在点击[是/否]的时候,动态控制姓名和地址栏只读

尝试把代码改为


    
        @**@
        @if (context.Complete)
        {
            
            
        }
        
        
    
    
        

运行之, 并没有达到预期. 无论怎么改变[是/否]检查框,姓名和地址栏都是可写的,因为渲染机制问题,所以要改一下思路.

正确方法是把逻辑包成一个组件,组件里面就可以局部刷新达到预期效果

9.新建组件 InputDIY.razor




    

     




@code{ [Parameter] public Foo? Context { get; set; } }

Index.razor代码改为


    
        
        
        
        
        
    
    
        

注:如果不加入以下写法,会照成InputDIY里面渲染一次Name列,FieldItems又渲染一次Name列.这是MS的内部机制一个小坑,暂时没有办法避开.


10.运行效果

Bootstrap Blazor 实战动态表单组件_第2张图片

11.数据验证 ValidateForm


    
        
            
            
            
            
            
        
        
            

Bootstrap Blazor 实战动态表单组件_第3张图片

12.DEMO源码

你可能感兴趣的:(BootstrapBlazor,Blazor,bootstrap,前端,html)