npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

legao-form

v0.0.14

Published

<p style="text-align: center"> <a href="https://www.npmjs.com/package/legao-form" target="blank"><img src="https://img12.360buyimg.com/imagetools/jfs/t1/116999/3/6618/21716/5ebcf703Ebfd265e2/4cc4be1aad9e30db.png" width="220" alt="legao-form Logo" /></a>

Downloads

8

Readme

Form 表单生成器,通过配置 FormData 即可生成可交互的 form 页面。

[TOC]

Usage

使用之前请先看说明文档,会让你节省百分之 80 的开发时间。

具体代码编写参考下方 demo。

详细介绍

FormItem 类型列表

  • [x] group 分组列表
  • [x] input 输入框
  • [x] textarea 大文本框
  • [x] select 下拉选择
  • [x] async_select 异步下拉选择
  • [x] radio 单选框
  • [x] checkbox 复选框
  • [x] date 日期
  • [x] upload 文件上传
  • [x] complex 多表单联动
  • [x] 表示已经实现的表单项。

FormContainer

| 属性 | 类型 | 含义 | 是否必填 | 备注说明 | | :------: | :------------------------------ | :--------------- | :------: | ------------------------------------------------------------------------ | | data | array<FormData> | 表单项数据数组 | 是 | | | isEdit | boolean | 表单整体模式 | 是 | true:编辑状态;false:只读状态 | | submit | Func:(values, form)=>void | 表单提交回调 | 是 | | | btnText | string | 表单提交按钮文本 | 是 | | | children | Func:(param: Object)=>ReactNode | 表单提交按钮文本 | 是 | 参数对象类型: param:{errors, handleSubmit, isSubmitting, handleReset} |

Group 属性配置

| 属性 | 类型 | 含义 | 是否必填 | 备注说明 | | :------: | :------ | :------------- | :------: | --------------------------------------------------- | | label | string | 表单项标题文本 | 是 | | | type | string | 表单类型 | 是 | 此项决定了表单项的展示类型 | | show | boolean | 是否显示 | - | | | grid | number | 栅格占位 | - | 页面分 24 份,整个 form item 所占宽度(包含 label) |

FormData 属性配置

| 属性 | 类型 | 含义 | 是否必填 | 备注说明 | | :------: | :-------------- | :------------- | :------: | ---------------------------------------------------------------------------------------- | | label | string | 表单项标题文本 | 是 | | | name | string | 表单项 属性名 | 是 | 表单提交 name,同一个 form 中 name 不能重复 | | type | string | 表单类型 | 是 | 此项决定了表单项的展示类型 | | value | string | 表单项的值 | 是 | string | checkbox 特殊为 array<string> | | show | boolean | 是否显示 | - | 该表单项是否显示 | | readonly | string | 是否只读 | 是 | 该表单项是否只读 | | grid | number | 栅格化布局 | - | 页面分 24 份,整个 form item 所占宽度(包含 label) | | schema | string<yup> | 表单验证条件 | - | 表单验证条件,集成 yup 框架进行表单验证 | | extra | object<Extra> | 表单项扩展属性 | - | 可对表单 label,表单元素单独控制,最终整个对象会透传给实际的表单元素,Extra 见下方说明 |

Extra 属性说明(不同属性,针对不同表单类型)

| 属性 | 类型 | 含义 | 是否必填 | 备注说明 | | :---------: | :---------------------- | :--------------------- | :------: | ---------------------------------------------------------------------------------- | | grid | number | 表单元素栅格占位 | - | 页面分 24 份,表单元素所占宽度(不包含 label) | | labelgrid | number | 表单 label 栅格占位 | - | 页面分 24 份,表单 label 所占宽度 | | placeholder | string | placeholder | - | 特指使用 input / textarea 时指定 placeholder | | options | array<OptionsObject> | 选项列表 | - | 特指使用 select / radio / checkbox 时指定 optionsOptionsObject见下方说明 | | action | string | 文件上传提交 action | - | 特指使用 upload 时指定 action,文件上传目标地址 | | callback | Func:(fileInfo:any)=>{} | 文件成功回调 | - | 特指使用 upload 时文件上传成功之后,对结果进行处理 | | child | array<FormItem> | 复合表单联动子表单元素 | - | 特指使用 complex 时 显示的子表单元素 FormItem 即为上面所有的普通表单项 |

OptionsObject 属性说明

| 属性 | 类型 | 含义 | 是否必填 | 备注说明 | | :---: | :----- | :-------------- | :------: | -------- | | value | string | option 实际值 | 是 | | | label | string | option 显示文本 | 是 | |

表单验证

每个表单项都可以配置 schema 来设置表单校验,该功能使用的是 yup 工具,如有需要可参考 yup 文档。

  • 特殊说明:每个表单配置表单校验,只需要在自己的数据结构中设置 schema 即可,嵌套表单同理设置嵌套的子表单校验即可

特别说明(多表单项联动)

多表单项联动就是单个表单的嵌套。

具体示例

  • demo 生成结果:

Demo

  • demo 示例代码:
import React, { Component } from "react";
import { FormContainer, FormSchema } from "legao-form";

function timeout(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}
const FormData = [
  {
    label: "普通表单项示例:",
    type: "group",
    show: false,
    grid: 24,
  },
  {
    label: "input1",
    name: "inputName1",
    value: "这个 input has value",
    type: "input",
    readonly: false,
    grid: 12,
    show: true,
    schema: FormSchema.string().required(),
    extra: {
      grid: 18,
      placeholder: "这个有value ,也有placeholder",
    },
  },
  {
    label: "input2",
    name: "inputName2",
    value: "",
    type: "input",
    readonly: true,
    grid: 12,
    show: true,
    schema: FormSchema.string().required(),
    extra: {
      grid: 8,
      placeholder: "这个没有value ,但是有placeholder",
    },
  },
  {
    label: "textarea",
    name: "textareaName",
    value: "",
    type: "textarea",
    show: true,
    readonly: true,
    grid: 24,
    extra: {
      grid: 18,
      placeholder: "placeholder 还是要有的哦, 可以用 grid 控制宽度",
    },
    schema: FormSchema.string().required(),
  },

  {
    label: "select",
    name: "selectName",
    value: "select1",
    type: "select",
    show: true,
    readonly: true,
    grid: 12,
    extra: {
      grid: 10,
      options: [
        { value: "select1", label: "options1" },
        { value: "select2", label: "options2" },
        { value: "select3", label: "options3" },
      ],
    },
    schema: FormSchema.string().required(),
  },
  {
    label: "async_select",
    name: "asyncSelectName",
    value: "",
    type: "async_select",
    readonly: true,
    grid: 12,
    extra: {
      grid: 10,
      loadOptions: async (input: string) => {
        await timeout(500);
        if (!input) {
          return [
            { value: "asyncSelect1", label: "asyncOpt1" },
            { value: "asyncSelect2", label: "asyncOpt2" },
            { value: "asyncSelect3", label: "asyncOpt3" },
          ];
        }
        return [
          { value: "asyncSelect1", label: "asyncOpt1" },
          { value: "asyncSelect2", label: "asyncOpt2" },
          { value: "asyncSelect3", label: "asyncOpt3" },
        ].filter((item) => item.value.indexOf(input) > -1);
      },
    },
    schema: FormSchema.string().required(),
  },
  {
    label: "radio",
    name: "radioName",
    value: "radio2",
    type: "radio",
    show: true,
    readonly: true,
    grid: 12,
    extra: {
      options: [
        { value: "radio1", label: "radioVal1" },
        { value: "radio2", label: "radioVal2" },
        { value: "radio3", label: "radioVal3" },
      ],
    },
    schema: FormSchema.string().required(),
  },
  {
    label: "checkbox",
    name: "checkboxName",
    value: ["checkbox1", "checkbox3"],
    type: "checkbox",
    show: true,
    readonly: false,
    grid: 12,
    extra: {
      grid: 14,
      options: [
        { value: "checkbox1", label: "商详" },
        { value: "checkbox2", label: "搜索" },
        { value: "checkbox3", label: "推荐" },
        { value: "checkbox4", label: "广告" },
      ],
    },
  },
  {
    label: "Date",
    name: "dateName",
    value: "2020/01/02",
    type: "date",
    show: false,
    readonly: true,
    grid: 12,
    extra: {
      grid: 14,
    },
    schema: FormSchema.string().required().length(10),
  },
  {
    label: "Upload",
    name: "file",
    type: "upload",
    show: true,
    readonly: true,
    grid: 12,
    extra: {
      grid: 14,
      action: "https://www.mocky.io/v2/5cc8019d300000980a055e76",
      callback: async (fileInfoResult: any) => {
        // callback 可以不传,不传就走 antd upload 默认处理逻辑
        console.log(
          "-----------130---------",
          fileInfoResult.file.response.url
        );
        return fileInfoResult.file.response.url;
      },
    },
    schema: FormSchema.string().required(),
  },
  {
    label: "复合表单项示例:",
    type: "group",
    show: false,
    grid: 24,
  },
  {
    label: "就你们",
    name: "complexName",
    value: "",
    type: "complex",
    show: false,
    readonly: true,
    grid: 24,
    extra: {
      grid: 14,
      child: [
        {
          label: "测试复合radio",
          name: "complexName",
          value: "1",
          type: "radio",
          show: false,
          readonly: true,
          grid: 24,
          extra: {
            grid: 14,
            options: [
              { value: "1", label: "是" },
              { value: "0", label: "否" },
            ],
          },
        },
        {
          label: "测试 Checkbox",
          name: "checkbox123",
          value: ["1", "3"],
          type: "checkbox",
          show: "values.complexName.complexName==1",
          readonly: false,
          grid: 24,
          extra: {
            grid: 14,
            options: [
              { value: "1", label: "商详" },
              { value: "2", label: "搜索" },
              { value: "3", label: "推荐" },
              { value: "4", label: "广告" },
            ],
          },
        },
      ],
    },
    schema: FormSchema.object({
      complexName: FormSchema.string().required(),
    }),
  },
  {
    label: "还有谁",
    name: "complexName2",
    value: "",
    type: "complex",
    show: false,
    readonly: true,
    grid: 24,
    extra: {
      grid: 14,
      child: [
        {
          label: "测试复合radio",
          name: "complexRadio",
          value: "1",
          type: "radio",
          show: false,
          readonly: true,
          grid: 24,
          extra: {
            grid: 14,
            options: [
              { value: "1", label: "其他" },
              { value: "0", label: "没了" },
            ],
          },
        },
        {
          label: "",
          name: "complexInput",
          value: "",
          type: "input",
          show: "values.complexName2.complexRadio==1",
          readonly: false,
          grid: 24,
          extra: {
            grid: 14,
          },
        },
      ],
    },
    schema: FormSchema.object({
      complexName: FormSchema.string().required(),
    }),
  },
  {
    label: "提交按钮:",
    type: "group",
    show: false,
    grid: 24,
  },
];

/**
 * Form 表单生成器,示例代码
 */
class App extends Component {
  state = {
    checked: 1,
  };

  changeRadio = (val: number) => {
    this.setState({
      checked: val,
    });
  };

  render() {
    return (
      <div>
        <div className="appContainer">
          <div className="radioDiv">
            <input
              type="radio"
              id="huey"
              name="drone"
              value="1"
              checked={this.state.checked === 1}
              onChange={this.changeRadio.bind(this, 1)}
            />
            <label htmlFor="huey">编辑</label>
          </div>

          <div className="radioDiv">
            <input
              type="radio"
              id="dewey"
              name="drone"
              value="0"
              checked={this.state.checked === 0}
              onChange={this.changeRadio.bind(this, 0)}
            />
            <label htmlFor="dewey">只读</label>
          </div>
        </div>

        <FormContainer
          data={FormData}
          width="100%"
          isEdit={this.state.checked === 1}
          submit={(values, form) => {
            console.log(values, "提交表单");
            form.setSubmitting(false);
          }}
          btnText="提交"
        >
          {({ errors, handleSubmit, isSubmitting, handleReset }) => {
            return (
              <a
                // disabled={isSubmitting}
                onClick={() => {
                  handleSubmit();
                }}
              >
                提交2
              </a>
            );
          }}
        </FormContainer>
      </div>
    );
  }
}

export default App;

意见或建议

有任何建议可以提交 issues,或者给我们发邮件。