Repository: IduxFE/components
Pull request #141 (2021-01-16 10:16:25)

feat(cdk:forms): add utils
## PR Checklist

Please check if your PR fulfills the following requirements:

- [x] The commit message follows [our guidelines](https://github.com/IduxFE/components/blob/main/docs/contributing.zh.md#commit)
- [x] Tests for the changes have been added/updated or not needed
- [x] Docs and demo have been added/updated or not needed

## PR Type

What kind of change does this PR introduce?

- [ ] Bugfix
- [x] Feature
- [ ] Component style update
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Application (the showcase website) / infrastructure changes
- [ ] Other... Please describe:

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

## What is the new behavior?

## Other information


codecov[bot]: # [Codecov](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=h1) Report
> Merging [#141](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=desc) (c153841) into [main](https://codecov.io/gh/IduxFE/components/commit/270719c8ee02bd1b0c89e6efa6fccc256810aa92?el=desc) (270719c) will **decrease** coverage by `0.08%`.
> The diff coverage is `83.33%`.

[![Impacted file tree graph](https://codecov.io/gh/IduxFE/components/pull/141/graphs/tree.svg?width=650&height=150&src=pr&token=PGAUXP06V3)](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##             main     #141      +/-   ##
==========================================
- Coverage   97.40%   97.32%   -0.09%     
==========================================
  Files          58       59       +1     
  Lines        1040     1046       +6     
  Branches      177      178       +1     
==========================================
+ Hits         1013     1018       +5     
  Misses         10       10              
- Partials       17       18       +1     
```


| [Impacted Files](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/cdk/forms/src/utils.ts](https://codecov.io/gh/IduxFE/components/pull/141/diff?src=pr&el=tree#diff-cGFja2FnZXMvY2RrL2Zvcm1zL3NyYy91dGlscy50cw==) | `83.33% <83.33%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=footer). Last update [270719c...c7c0803](https://codecov.io/gh/IduxFE/components/pull/141?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/packages/cdk/forms/docs/index.zh.md b/packages/cdk/forms/docs/index.zh.md
index f0ecd409..7c4c4a87 100644
--- a/packages/cdk/forms/docs/index.zh.md
+++ b/packages/cdk/forms/docs/index.zh.md
@@ -8,9 +8,9 @@ cover:
 
 参考自 [@angular/forms](https://angular.cn/guide/forms-overview)
 
-- 显式创建表单模型
-- 函数式的表单验证：内置常用的，提供扩展接口
-- 表单状态管理：valid，invalid, validing，untouched，touched
+- 显示创建表单模型: `FormGroup`, `FormArray`, `FormControl`
+- 易扩展的表单验证: `Validators`, `ValidatorFn`, `ValidatorFn`
+- 响应式的表单状态: `valid`, `invalid`, `validating`, `blurred`, `unblurred`
 
 ## 何时使用
 
@@ -35,9 +35,9 @@ cover:
 | `required` | 验证表单控件具有非空值 | - | - | 验证失败返回 `{ required: { message: '' } }`|
 | `requiredTrue` | 验证表单控件的值为 `true` | - | - | 验证失败返回 `{ requiredTrue: { message: '', actual: value } }`|
 | `email` | 验证表单控件的值是否为 `email` | - | - | 验证失败返回 `{ email: { message: '', actual: value } }`|
-| `min()` | 验证表单控件的值大于或等于指定的数字 | number | - | 验证失败返回 `{ min: { message: '', min, actual: value } }`|
-| `max()` | 验证表单控件的值小于或等于指定的数字 | number | - | 验证失败返回 `{ max: { message: '', min, actual: value } }`|
-| `minLength()` | 验证表单控件的值的长度大于或等于指定的数字 | number | - | 验证失败返回 `{ minLength: { message: '', minLength, actual: value.length } }`|
-| `maxLength()` | 验证表单控件的值的长度小于或等于指定的数字 | number | - | 验证失败返回 `{ maxLength: { message: '', maxLength, actual: value.length } }`|
+| `min()` | 验证表单控件的值大于或等于指定的数字 | `number` | - | 验证失败返回 `{ min: { message: '', min, actual: value } }`|
+| `max()` | 验证表单控件的值小于或等于指定的数字 | `number` | - | 验证失败返回 `{ max: { message: '', min, actual: value } }`|
+| `minLength()` | 验证表单控件的值的长度大于或等于指定的数字 | `number` | - | 验证失败返回 `{ minLength: { message: '', minLength, actual: value.length } }`|
+| `maxLength()` | 验证表单控件的值的长度小于或等于指定的数字 | `number` | - | 验证失败返回 `{ maxLength: { message: '', maxLength, actual: value.length } }`|
 | `pattern()` | 验证表单控件的值匹配一个正则表达式 | `string \| RegExp` | - | 验证失败返回 `{ pattern: { message: '', pattern, actual: value } }`|
-| `setMessages()` | 设置验证失败的提示信息 | ErrorMessages | - | 每次设置的 `messages` 会跟之前的进行合并 |
+| `setMessages()` | 设置验证失败的提示信息 | `ErrorMessages` | - | 每次设置的 `messages` 会跟之前的进行合并 |
diff --git a/packages/cdk/forms/index.ts b/packages/cdk/forms/index.ts
index a8d8322d..baddc78a 100644
--- a/packages/cdk/forms/index.ts
+++ b/packages/cdk/forms/index.ts
@@ -4,4 +4,5 @@ export * from './src/controls/formControl'
 export * from './src/controls/formGroup'
 export * from './src/types'
 export * from './src/useForms'
+export * from './src/utils'
 export * from './src/validators'
diff --git a/packages/cdk/forms/src/utils.ts b/packages/cdk/forms/src/utils.ts
new file mode 100644
index 00000000..5a662fd1
--- /dev/null
+++ b/packages/cdk/forms/src/utils.ts
@@ -0,0 +1,15 @@
+import type { InjectionKey } from 'vue'
+import type { AbstractControl } from './controls/abstractControl'
+
+import { inject, provide } from 'vue'
+
+const token: InjectionKey<AbstractControl> = Symbol()
+
+export function provideControl(control: AbstractControl): void {
+  provide(token, control)
+}
+
+export function injectControl(path: Array<string | number> | string): AbstractControl | null {
+  const controlParent = inject(token)
+  return controlParent ? controlParent.get(path) : null
+}


Test patch:
diff --git a/packages/cdk/forms/__tests__/utils.spec.ts b/packages/cdk/forms/__tests__/utils.spec.ts
new file mode 100644
index 00000000..b5c65103
--- /dev/null
+++ b/packages/cdk/forms/__tests__/utils.spec.ts
@@ -0,0 +1,55 @@
+import { flushPromises, mount } from '@vue/test-utils'
+import { ComponentOptions } from 'vue'
+import { AbstractControl } from '../src/controls/abstractControl'
+import { useFormControl, useFormGroup } from '../src/useForms'
+import { injectControl, provideControl } from '../src/utils'
+
+const notFindText = 'not find control'
+
+const getComp = () => {
+  return {
+    template: `<div>{{ modelRef }}</div>`,
+    setup() {
+      const { modelRef } = injectControl('control') || { modelRef: notFindText }
+      return { modelRef }
+    },
+  }
+}
+
+const getApp = (Comp: ComponentOptions, control: AbstractControl) => {
+  return mount({
+    components: { Comp },
+    template: `<Comp />`,
+    setup() {
+      provideControl(control)
+    },
+  })
+}
+
+describe('utils.ts', () => {
+  test('basic work', async () => {
+    const control = useFormControl('text')
+    const group = useFormGroup({ control })
+    const app = getApp(getComp(), group)
+
+    expect(app.text()).toEqual('text')
+
+    control.setValue('text1')
+    await flushPromises()
+
+    expect(app.text()).toEqual('text1')
+  })
+
+  test('not find control work', async () => {
+    const group = useFormGroup({})
+    const app = getApp(getComp(), group)
+
+    expect(app.text()).toEqual(notFindText)
+  })
+
+  test('not provide work', async () => {
+    const app = mount(getComp())
+
+    expect(app.text()).toEqual(notFindText)
+  })
+})