首页 > 其他分享 >Bootstrap Blazor 实战动态表单组件

Bootstrap Blazor 实战动态表单组件

时间:2023-08-25 16:14:54浏览次数:46  
标签:Random Name get Bootstrap Display 表单 Blazor Foo public

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 文件中

删除 <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />

并在下面添加三行

<link href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" rel="stylesheet" />
<link href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" rel="stylesheet" />

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

<script src="_framework/blazor.server.js"></script> 之前添加

<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js" asp-append-version="true"></script>

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

@using BootstrapBlazor.Components

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

<BootstrapBlazorRoot>
    <Router AppAssembly="@typeof(App).Assembly">
        ...
    </Router>
</BootstrapBlazorRoot>

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

builder.Services.AddSingleton<WeatherForecastService>(); 后加入

builder.Services.AddBootstrapBlazor();

6.添加EditorForm测试代码

Index.razor

<EditorForm Model="@Model">
    <FieldItems>
        <EditorItem @bind-Field="@context.Name" />
        <EditorItem @bind-Field="@context.Education" />
        <EditorItem @bind-Field="@context.Complete" />
    </FieldItems>
    <Buttons>
        <Button Icon="fa-solid fa-floppy-disk" Text="提交" />
    </Buttons>
</EditorForm>

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; }

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

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

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

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

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

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

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

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

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

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

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

    /// <summary>
    /// 生成Foo类,随机数据
    /// Generate Foo class, random data
    /// </summary>
    /// <param name="localizer"></param>
    /// <returns></returns>
    public static Foo Generate(IStringLocalizer<Foo> 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
    };

    /// <summary>
    /// 生成 Foo 类,随机数据
    /// Generate Foo class, random data
    /// </summary>
    /// <returns>返回一个Foo类的List,Return a List of Foo class</returns>
    public static List<Foo> 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();

  
    /// <summary>
    /// 通过 Count 获得颜色
    /// </summary>
    /// <param name="count"></param>
    /// <returns></returns>
    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
    };

    /// <summary>
    /// 通过 Id 获取 Title
    /// </summary>
    /// <returns></returns>
    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"
    };

    /// <summary>
    /// 
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public static string GetTitle(int id) => Cache.GetOrAdd(id, key => GetTitle());

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

    private static ConcurrentDictionary<int, string> Cache { get; } = new();
    #endregion
}

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

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

7.运行

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

尝试把代码改为

<EditorForm Model="@Model">
    <FieldItems>
        @*<InputDIY Context="@context" />*@
        @if (context.Complete)
        {
            <EditorItem @bind-Field="@context.Name" Readonly="@context.Complete" />
            <EditorItem @bind-Field="@context.Education" Readonly="@context.Complete" />
        }
        <EditorItem @bind-Field="@context.DateTime" Readonly="true" />
        <EditorItem @bind-Field="@context.Complete" />
    </FieldItems>
    <Buttons>
        <Button Icon="fa-solid fa-floppy-disk" Text="提交" />
    </Buttons>
</EditorForm>

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

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

9.新建组件 InputDIY.razor


<Row>

    <BootstrapInput @bind-Value="@Context!.Name" IsDisabled="@Context!.Complete" ShowLabel="true" />

    <BootstrapInput @bind-Value="@Context!.Education" IsDisabled="@Context!.Complete" ShowLabel="true" /> 

</Row>

<br />

@code{

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

}

Index.razor代码改为

<EditorForm Model="@Model">
    <FieldItems>
        <InputDIY Context="@context" />
        <EditorItem @bind-Field="@context.Name" Editable="@context.Complete" />
        <EditorItem @bind-Field="@context.Education" Editable="@context.Complete" />
        <EditorItem @bind-Field="@context.DateTime" Readonly="true" />
        <EditorItem @bind-Field="@context.Complete" />
    </FieldItems>
    <Buttons>
        <Button Icon="fa-solid fa-floppy-disk" Text="提交" />
    </Buttons>
</EditorForm>

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

<EditorItem @bind-Field="@context.Name" Editable="@context.Complete" />

10.运行效果

11.数据验证 ValidateForm

<ValidateForm Model="@Model">
    <EditorForm TModel="Foo">
        <FieldItems>
            <InputDIY Context="@context" />
            <EditorItem @bind-Field="@context.Name" Editable="@context.Complete" />
            <EditorItem @bind-Field="@context.Education" Editable="@context.Complete" />
            <EditorItem @bind-Field="@context.DateTime" Readonly="true" />
            <EditorItem @bind-Field="@context.Complete" />
        </FieldItems>
        <Buttons>
            <Button ButtonType="ButtonType.Submit" Icon="fa-solid fa-floppy-disk" Text='提交' />
        </Buttons>
    </EditorForm>
</ValidateForm>

12.DEMO源码

标签:Random,Name,get,Bootstrap,Display,表单,Blazor,Foo,public
From: https://www.cnblogs.com/densen2014/p/17657176.html

相关文章

  • element-ui(Form 表单)
    在Form组件中,每一个表单域由一个Form-Item组件构成,表单域中可以放置各种类型的表单控件,包括Input、Select、Checkbox、Radio、Switch、DatePicker、TimePicker<el-formref="form":model="form"label-width="80px"><el-form-itemlabel="活动名称">......
  • 使用bootstrap总结
    bootstrap是个很不错的前端css框架,把很多按钮、表单、表格、图片css通用样式都写好了,而且浏览器兼容不需我们考虑尤其是它的栅格系统很强大,在做响应式布局时候很有用,但是默认支持12列,一般也足够了,如果要自定义列,就要它的less我没用过,网站性能优化里面有提尽量少用css表达式<!DOC......
  • element表单验证~提交
    ......
  • Angular:表单设置动态校验规则(ngZorro示例)
    背景有时我们需要根据不同的条件,决定表单控件是否是必填的。代码示例HTML文件<formnz-form[formGroup]="validateForm"(ngSubmit)="submitForm()"><nz-form-item><nz-form-label[nzSpan]="4"nzRequirednzFor="name">Name</nz-f......
  • MAUI+Masa Blazor APP 各大商店新手发布指南-小米篇
    目录前言审核注意事项准备材料测试与审核总结前言先说一下我们上架厂家应用商店的原因:除了方便用户下载之外,需要厂家的离线推送和微信内容分享等都需要上架应用商店(微信分享不上架有调用次数限制)。如果你的App需要在国内使用离线推送功能,也就是App不启动的场景下接收消息推送,......
  • JVS低代码中表单引擎与逻辑引擎是如何联合调用外部API的?
    在企业项目中,常常出现需要给外部系统提供一个api,让外部系统触发调用,本系统直接数据入库,那么我们来看看jvs的表单引擎与逻辑引擎联合实现这个功能,先看实现效果:配置步骤:一、配置列表页如下图所示:①选中需要增加列表页的目录,在目录操作的主界面上②点击创建列表页设计,系统进入列表页......
  • bh002- Blazor hybrid / Maui 保存设置快速教程
    1.建立工程bh002_ORM源码2.添加nuget包<PackageReferenceInclude="BootstrapBlazor.WebAPI"Version="7.*"/><PackageReferenceInclude="FreeSql"Version="*"/><PackageReferenceInclude="FreeSql.Provid......
  • vue实现简单表单收集
    vue实现简单表单收集实现<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><scriptsrc="......
  • 表单自动填充属性 autocomplete
    摘抄自:HTML属性:autocomplete-HTML(超文本标记语言)|MDN(mozilla.org)表单自动填充不同类型<!--该字段期望该值是一个人的全名--><inputname="name"id="name"autocomplete="name"/><!--该字段期望该值是一个电子邮件值--><inputname="email"id=&q......
  • Blazor前后端框架Known-V1.2.13
    V1.2.13Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。Gitee:https://gitee.com/known/KnownGithub:https://github.com/known/Known概述基于C#和Blazor实现的快速开发框架,前后端分离,开箱即用。跨平台,单页应用,混合桌面应用,Web和桌面......