Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Form & FormItem component #108

Merged
merged 62 commits into from
Nov 14, 2023

Conversation

moushicheng
Copy link
Contributor

@moushicheng moushicheng commented Aug 19, 2023

Preview

<script lang="ts">
	import { KForm, createKFormInstance, KFormItem } from '@ikun-ui/form';
	import { IKunFormInstance } from '@ikun-ui/utils';
        let form: IKunFormInstance = createKFormInstance();
</script>
<KForm bind:form>
	----Form----
	<KFormItem label={'name'} field={'name'} required>
		<KInput placeholder="inputValue"></KInput>
	</KFormItem>
	<KFormItem label={'password'} field={'password'} rules={string([minLength(1), endsWith('#any')])}>
		<KInput placeholder="inputValue"></KInput>
	</KFormItem>

	<KFormItem field={'another'}>
		<KFormItem label={'a'} field={'a'}>
			<KInput placeholder="inputValue"></KInput>
		</KFormItem>
		<KFormItem label={'b'} field={'b'}>
			<KInput placeholder="inputValue"></KInput>
		</KFormItem>
	</KFormItem>
	<KButton
		on:click={() => {
			form.validateValues();
			const values = form.submit();
			console.log(values);
		}}>Submit</KButton
	>
	<KButton
		on:click={() => {
			form.setValues({
				name: 'ikun',
				password: 'moushicheng#any',
				another: { a: 1, b: 2 },
				accept: true,
				darkMode: true,
				IKun: true,
				select: 'Large'
			});
		}}>SetValue</KButton
	>
	<KButton
		on:click={() => {
			form.resetValues();
		}}>ResetValues</KButton
	>
	----Form----
</KForm>

Featuret:

  • nested FormItem
  • form series capability
export type IKunFormInstance = {
	//record Field value
	values: any;
	//record Field Contexts
	contexts: Contexts;
	//get Field Values
	submit: () => void;
	//validate all Field value
	validateValues: () => boolean;
	//get specific Field value
	getValue: (path: string) => any;
	//set specific Field value
	setValue: (path: string, value: any) => void;
	//set all Field value
	setValues: (values: any) => void;
	//record specific contexts into IKunFormInstance.contexts
	setContext: (path: string, context: FormContext) => void;
	//reset Field Values using field contexts inititalValue
	resetValue: (path: string) => void;
	//reset all Field Values
	resetValues: () => void;
	//subscribe specific Field change ,callback will be called when change
	subscribe: (path: string, callback: (values: any) => void) => void;
	//subscribe all Field change,callback will be called when change
	subscribes: (callback: (values: any) => void) => void;
};
  • FormItem
       // props
	export let label: string = ''; //field label name
	export let field: string = ''; //field name
	export let initialValue: string = ''; //initialValue will use in calling form.resetValue 
	export let rules: BaseSchema | undefined = void 0; //field validate rules, it need pass valibot schema
	export let required: boolean = false; //is require? if value is empty,it'll be intercepted by the validate function
     //FormIten instance
    export type FormContext = {
	form: IKunFormInstance;
	path: string;
	__FormContext__: true;
	initialValue: any;
	validateField: () => Issue[];
	updateField: IKunUpdateField;
	subscribe: (value?: any) => void;
	initialField: (value?: any) => void;
	resetField: () => void;
     };
  • use valibot to validate field

TODO:

  • form validate

  • support Form components(Switch,CheckBox) to use inside FormItem
    (only need to bind the field bidirectionally)

  • and so on.....

@netlify
Copy link

netlify bot commented Aug 19, 2023

Deploy Preview for ikun-ui ready!

Name Link
🔨 Latest commit f981fa2
🔍 Latest deploy log https://app.netlify.com/sites/ikun-ui/deploys/65530cc79608230008735d04
😎 Deploy Preview https://deploy-preview-108--ikun-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

components/Form/src/helper.ts Outdated Show resolved Hide resolved
@moushicheng moushicheng reopened this Aug 29, 2023
callback: (node: FormContext) => void
) => {
function traverse(node: Contexts) {
if (node.__FormContext__) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个判断什么情况下会命中?我调试你给的例子中似乎没有进入过

Copy link
Contributor Author

@moushicheng moushicheng Sep 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Form
    • FormItem.a
      • FormItem.a1
      • FormItem.a2

这样的Form转化过来的Context的实际结构

{
   __this__: FormContext a
   a1:{
      __this__: FormContext a1
   }
   a2:{
     __this:__: FormContext a2
   }
}

如果不判断if(node.FormContext)
遍历第一层则会遍历到三个属性__this__,a1,a2但这并不是FormContext结构。

anotherNodesKeys.forEach((item) => {
traverse(node[item]);
});
callback(currentContext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个为什么不和重置一样,只对anotherNodesKeys.length === 0的上下文对象调用验证函数?

Copy link
Contributor Author

@moushicheng moushicheng Sep 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

因为FormItem可以嵌套,我们可以设想这么一个结构

  • Form
    • FormItem.a
      • FormItem.a1
      • FormItem.a2
    • FormItem.b

有anotherNodesKeys.length === 0的情况, 意味着只遍历没有子节点的Context,在这个结构里只会遍历到a1、a2、b这类边缘节点。

如果没有anotherNodesKeys.length === 0,则a,a1,a2,b都会遍历到
validateValues需要遍历所有节点(a,a1,a2,b),这是因为用户可能在FormItem.a上设置rules(校验规则),我们允许直接在a上写rules。

而像resetValues(重置所有字段) 我们只需要重置a1,a2和b 这些边缘节点就好了,因为如果重置了a1,a2,再去重置a是冗余操作。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

顺带一提,当时调研validate用什么库,我最终选择了valibot这个库,如果有不妥的地方我们可以再讨论讨论

Copy link
Member

@baiwusanyu-c baiwusanyu-c Oct 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateValues需要遍历所有节点(a,a1,a2,b),这是因为用户可能在FormItem.a上设置rules(校验规则),我们允许直接在a上写rules。

我理解在整个数据结构上可能是 const form = { a: {a1:‘xxx’, a2: 'xxx'}, b: 'xxx'}, 我无法想象在对a1 和 a2 进行校验后还需要对 a 做什么样的校验

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

顺带一提,当时调研validate用什么库,我最终选择了valibot这个库,如果有不妥的地方我们可以再讨论讨论

valibot 库有什么优势?作为组件,我们只需要封装非空校验,复杂的校验应该由用户去完成,也就是说我认为应该让用户去使用 valibot ,而不是把它加入到组件库中

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateValues需要遍历所有节点(a,a1,a2,b),这是因为用户可能在FormItem.a上设置rules(校验规则),我们允许直接在a上写rules。

我理解在整个数据结构上可能是 const form = { a: {a1:‘xxx’, a2: 'xxx'}, b: 'xxx'}, 我无法想象在对a1 和 a2 进行校验后还需要对 a 做什么样的校验

主要是允许用户在任意FormItem上写rules都生效,否则某用户直接在a上写rules,而a1和a2的rules===undefined的情况下,交验逻辑会失效

baiwusanyu-c and others added 3 commits October 12, 2023 23:32
# Conflicts:
#	components/Checkbox/src/index.svelte
#	components/Radio/src/index.svelte
#	components/Switch/src/index.svelte
#	components/index.ts
#	pnpm-lock.yaml
#	preset/src/shortcuts/index.ts
# Conflicts:
#	components/Select/package.json
#	components/Select/src/index.svelte
#	components/index.ts
#	pnpm-lock.yaml
#	preset/src/shortcuts/index.ts
@baiwusanyu-c baiwusanyu-c changed the base branch from main to feat/k-form November 14, 2023 06:08
@baiwusanyu-c baiwusanyu-c merged commit cece08a into ikun-svelte:feat/k-form Nov 14, 2023
4 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants