Bootstrap Blazor 实战动态表单组件

news2024/11/18 22:57:29

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源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/928201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

秒杀系统的业务流程以及优化方案(实现异步秒杀)

先看基本的业务流程 那么我们可以看到整个流程都是一个线程来完成的&#xff0c;这样的话耗时还是很长的&#xff0c;那么可不可以采用多线程去实现呢&#xff1f; 首先我们要思考怎么对业务进行拆分&#xff0c;可以想象一个我们去饭店点餐&#xff0c;会有前台接待&#xff…

react antd框架中的徽标获取数据对应状态的数量

实现思路&#xff1a;获取数量的思路是通过filter过滤符合数据来实现。 列表数组.filter(item > item.status 值).length; 例子&#xff1a;以下这个例子是判断data数组中的status中在职的数量。 data.filter((item) > item.status 在职).length 效果展示&#xff…

Python 练习:剔除数字

练习&#xff1a;剔除数字&#xff1a; 要求如下&#xff1a; 1、编写一段程序代码&#xff0c;程序运行后&#xff0c; 需要用户随意输入一段包含有数字和字母的字符串&#xff1b; 2、程序会自动删除字符串中的数字&#xff0c; 然后输出一串没有数字的字符串&#xff08;纯…

yyyy-MM-dd‘T‘HH:mm时间格式探索

yyyy-MM-ddTHH:mm:ss 一直以后这个T是为了避免yyyy-MM-dd HH:mm:ss空格出现解析报错 但是这个T实际是一个标识符&#xff0c;作为小时元素的开始。 T代表后面跟着是时间&#xff0c;Z代表0时区&#xff08;相差北京时间8小时&#xff09; T 即代表 UTC&#xff08;Coodinated U…

MyBatis与spring集成

目录 MyBatis与Spring集成 导入pom依赖 导入generatorConfig.xml 导入spring-mybatis.xml 自动生成mapper文件 编写接口类&#xff1a;BookBiz aop整合PageHelper分页插件 编写分页查询 编写pagebean 编写PagerAspect类 测试结果 MyBatis与Spring集成 导入pom依赖 &l…

最新SQLMap安装与入门技术

SQLMap详解 SQLMap是一个自动化的SQL注入工具&#xff0c;其主要功能是扫描、发现并利用给定URL的SQL注入漏洞。SQLMap内置了很多绕过插件&#xff0c;支持的数据库是MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、IBM DB2、SQLite、Firebird、Sybase和…

网工内推 | 上市公司、国企招网工,五险一金,包吃包住

01 宁波领越智能设备有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1&#xff1a;负责集团内部网络运维安全管理工作和数据中心管理 2&#xff1a;挖掘和发现目前整体网络运行体系中存在的问题和不足&#xff0c;提出具体改进方案并推进实施。 3&#xff1a;…

uni-app-微信公众号静默授权

文章目录 前言一、onLoad钩子中调用二、使用步骤截取url中的code 前言 提示&#xff1a;&#xff1a;公司的公众号用户&#xff0c;与后台系统的账号系统做绑定&#xff0c;用以推送消息 公众号自定义菜单直接链接到以下页面&#xff0c;进行静默授权&#xff0c;然后用户输入…

AIGC数据处理与存储解决方案

2023年数智中国AIGC科技周 AI云智上海专场在普陀区召开。活动以“智能涌现”、“算力突围”、“超越现实”三大篇章开启&#xff0c;第一篇章以“智能涌现”开幕、重塑数实融合终极愿景&#xff1b;第二篇章“算力突围”&#xff0c;以AI为引擎&#xff0c;以计算为基石&#x…

Java——一个简单的使用JPanel和JButton来设计窗口界面

这段代码是一个简单的使用JPanel和JButton来设计窗口界面的例子。 在designFrame方法中&#xff0c;创建了一个JFrame对象作为窗口&#xff0c;然后创建了两个JPanel对象作为面板&#xff0c;分别用于放置按钮。 创建了两个JButton对象作为按钮&#xff0c;并设置按钮的文本内容…

【谷粒商城】环境搭建一:Docker容器部署

Docker容器部署 VMware虚拟机安装 参考&#xff1a;VMware虚拟机安装Linux教程 Docker安装 Linux安装Docker # 1.更新apt包索引 sudo apt-get update# 2.安装以下包以使apt可以通过HTTPS使用存储库&#xff08;repository&#xff09; sudo apt-get install -y apt-transpor…

火狐渗透浏览器免安装版

火狐浏览器免安装版 &#x1f4ce;网安火狐Firefox直接使用无需安装.zip 火狐浏览器设置代理&#xff0c;方便burp抓包 参考&#xff1a;burpsuite简单抓包教程_burpsuite抓包_Xiongcanne的博客-CSDN博客

从程序员进阶到架构师再到CTO,该如何破解焦虑?

引言 我们生活的时代&#xff0c;变化太快&#xff0c;许多人在职业发展的道路上都会面临焦虑与迷茫。这种焦虑源自我们内心的不安&#xff0c;也来自于外部形势的变化。 对于技术从业者来说&#xff0c;焦虑并不会随着职业发展而自动消失&#xff0c;不同职场阶段会面临不同的…

SSL/TLS协议的概念、工作原理、作用以及注意事项

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、SSL/TLS协议的基本概念 二、SSL/TLS的工作…

VBA_MF系列技术资料1-167

MF系列VBA技术资料 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-04属于定…

苹果新健康专利:利用 iPhone、Apple Watch 来分析佩戴者的呼吸情况

根据美国商标和专利局&#xff08;USPTO&#xff09;公示的清单&#xff0c;苹果获得了一项健康相关的技术专利&#xff0c;可以利用 iPhone、Apple Watch 来分析佩戴者的呼吸系统。 苹果在专利中概述了一种测量用户呼吸功能的系统&#xff0c;通过 iPhone 上的光学感测单元&am…

前端需要理解的设计模式知识

设计模式的原则&#xff1a;1. 单一职责原则&#xff08;一个对象或方法只做一件事&#xff09; 2. 最少知识原则&#xff08;尽可能少的实体或对象间互相作用&#xff09; 3. 开放封闭原则&#xff08;软件实体具有可扩展且不可修改&#xff09; 设计模式是通过代码设计经验总…

2021年12月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题:移动路线 桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把蚂蚁的右脚弄伤了,于是蚂蚁只能向上或向右…

基于PIC单片机温度-脉搏-DS18B20温度-液晶12864显示(proteus仿真+源程序)

一、系统方案 1、上电初始化液晶第一行显示脉搏&#xff0c;第二行显示温度&#xff0c;第三行显示模式&#xff0c;第四行显示强度&#xff1b;按下K1按键可以选择模式&#xff0c;催眼模式或治疗模式。 2、治疗模块下&#xff0c;可以通过K2、K3修改强度。 二、硬件设计 原理…

探索数据湖中的巨兽:Apache Hive分布式SQL计算平台浅度剖析!

文章目录 ◆ Apache Hive 概述1.1 分布式SQL计算1.2 Hive的优势 ◆ 模拟实现Hive功能2.1 元数据管理2.2 解析器2.3 基础架构2.4 Hive架构 ◆ Hive基础架构3.1 Hive架构图3.2 Hive组件3.2.1 元数据存储3.2.2 Driver驱动程序3.2.3 用户接口 ◆ Hive部署4.1 VMware虚拟机部署步骤一…