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(cdk:forms): add useuseAccessorAndControl, useAccessor, useControl #1012

Merged
merged 1 commit into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions packages/cdk/forms/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import { DOMWrapper, flushPromises, mount } from '@vue/test-utils'
import { computed, provide } from 'vue'
import { provide } from 'vue'

import { Validators } from '..'
import { FormGroup } from '../src/controls'
import { useFormGroup } from '../src/useForms'
import { FORMS_CONTROL_TOKEN, useValueAccessor, useValueControl } from '../src/utils'
import { FORMS_CONTROL_TOKEN, useAccessorAndControl, useControl } from '../src/utils'

const InputComponent = {
template: `<input :value="valueRef" @input="onInput" @blur="onBlur" />`,
props: ['value', 'control'],
template: `<input :value="accessor.value" :disabled="accessor.disabled" @input="onInput" @blur="onBlur" />`,
props: ['value', 'control', 'disabled'],
emits: ['update:value'],
setup() {
const control = useValueControl()
const accessor = useValueAccessor({ control })
const valueRef = computed(() => accessor.valueRef.value)
const { accessor } = useAccessorAndControl()
const onInput = (evt: Event) => accessor.setValue((evt.target as HTMLInputElement).value)
const onBlur = () => accessor.markAsBlurred()
return { valueRef, onInput, onBlur }
return { accessor, onInput, onBlur }
},
}

const FormComponent = {
template: `<form><slot /></form>`,
props: ['control'],
setup() {
const control = useValueControl()
const control = useControl()
provide(FORMS_CONTROL_TOKEN, control)
},
}
Expand Down
4 changes: 2 additions & 2 deletions packages/cdk/forms/demo/CustomForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ title:

自定以一个支持 `AbstractControl` 的表单组件。

更多实现细节,请参考:[IxForm](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/Form.tsx) 与 [IxFormItem](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/FormItem.tsx)。
更多实现细节,请参考:[Form](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/Form.tsx) 与 [FormItem](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/FormItem.tsx)。

## en

Customize with a form component that supports `AbstractControl`.

For more implementation details, see: [IxForm](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/Form.tsx) and [IxFormItem](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/FormItem.tsx).
For more implementation details, see: [Form](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/Form.tsx) and [FormItem](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/FormItem.tsx).
10 changes: 5 additions & 5 deletions packages/cdk/forms/demo/CustomForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
<script setup lang="ts">
import { provide } from 'vue'

import { FORMS_CONTROL_TOKEN, useValueControl } from '@idux/cdk/forms'
import { FORMS_CONTROL_TOKEN, useControl } from '@idux/cdk/forms'

defineProps<{
control?: string | object
control?: string | number | (string | number)[] | object
}>()

// 使用 valueControl 接管 props.control 的控制
const control = useValueControl()
// 通过 props.control 拿到真正的 control(AbstractControl)
const control = useControl()

// 注入父 control, 以便子组件通过 key 获取对应的子 control
// 注入 control, 以便子组件通过 key 获取对应的子 control
provide(FORMS_CONTROL_TOKEN, control)
</script>

Expand Down
4 changes: 2 additions & 2 deletions packages/cdk/forms/demo/CustomInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ title:

自定义一个支持 `AbstractControl` 的输入控件。

更多实现细节,请参考:[IxInput](https://github.com/IDuxFE/idux/blob/main/packages/components/input/src/Input.tsx) 或其他输入型组件。
更多实现细节,请参考:[Input](https://github.com/IDuxFE/idux/blob/main/packages/components/input/src/Input.tsx) 或其他输入型组件。

## en

Customize with an input control that supports `AbstractControl`.

For more implementation details, see: [IxForm](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/Form.tsx) or other input components.
For more implementation details, see: [Input](https://github.com/IDuxFE/idux/blob/main/packages/components/form/src/Input.tsx) or other input components.
20 changes: 7 additions & 13 deletions packages/cdk/forms/demo/CustomInput.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
<template>
<input class="custom-input" :value="valueRef" :disabled="isDisabled" @blur="onBlur" @input="onInput" />
<input class="custom-input" :value="accessor.value" :disabled="accessor.disabled" @blur="onBlur" @input="onInput" />
</template>

<script setup lang="ts">
import { computed } from 'vue'

import { useValueAccessor, useValueControl } from '@idux/cdk/forms'
import { useAccessorAndControl } from '@idux/cdk/forms'

defineProps<{
value?: string
control?: string | object
control?: string | number | (string | number)[] | object
disabled?: boolean
value?: string
}>()

// 使用 valueAccessor 接管 props.value 的控制
const control = useValueControl()
const accessor = useValueAccessor({ control })
// useAccessorAndControl 内部对 props 中的 control, disabled, value 进行了处理
const { accessor } = useAccessorAndControl()

// 表单绑定的值
const valueRef = computed(() => accessor.valueRef.value)
// 表单禁用状态
const isDisabled = computed(() => accessor.disabled.value)
// 表单 blur 状态
const onBlur = () => {
accessor.markAsBlurred()
}

// 表单值发生变更后的回调
const onInput = (evt: Event) => {
const { value } = evt.target as HTMLInputElement
Expand Down
64 changes: 26 additions & 38 deletions packages/cdk/forms/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,70 +115,58 @@ export function useFormControl<T>(

更多默认的提示信息,参见 [messages](https://github.com/IDuxFE/idux/tree/main/packages/cdk/forms/src/messages)

### useValueControl
### useAccessorAndControl

> 创建 AbstractControl,会通过 inject 从父组件中获取。
> 构建 `accessor`, 来接管表单控件 `props` 的 `control` 和 `value`, `disabled` 状态的优先级关系。
> 当 `control` 存在时,`value` 和 `disabled` 无效,以 `control` 的状态为准。

```ts
export function useValueControl<T>(options?: ValueControlOptions): ShallowRef<AbstractControl<T> | undefined>

export interface ValueControlOptions {
/**
* 通过 props 获取 control 的 key
*/
controlKey?: string
export function useAccessorAndControl<T = any>(options?: FormAccessorOptions): {
accessor: FormAccessor<T>;
control: ShallowRef<AbstractControl<T> | undefined>;
}
```

### useValueAccessor

> 创建 ValueAccessor,用户处理 props 中 `value` 和 `control` 的优先级关系。
export function useAccessor<T = any>(control: ShallowRef<AbstractControl<T> | undefined>, valueKey?: string, disabledKey?: string): FormAccessor<T>

```ts
export function useValueAccessor<T>(options: ValueAccessorOptions): ValueAccessor<T>
export function useControl<T = any>(controlKey?: string): ShallowRef<AbstractControl<T> | undefined>

export interface ValueAccessorOptions<T> {
export interface FormAccessorOptions {
/**
* 通过 props 获取 control 的 key
* props 中 control 的 key
*
* @default 'control'
*/
control: ShallowRef<AbstractControl<T> | undefined>
controlKey: string
/**
* 通过 props 获取 value 的 key
* props 中 value 的 key
*
* @default 'value'
*/
valueKey?: string
/**
* 通过 props 获取 disabled 的 key
* props 中 disabled 的 key
*
* @default 'disabled'
*/
disabledKey?: string
}

export interface ValueAccessor<T> {
export interface FormAccessor<T = any> {
/**
* 响应式的控件值
* 控件的值
*/
valueRef: ComputedRef<T>
value: T
/**
* 响应式的控件禁用状态
* 禁用状态
*/
disabled: ComputedRef<boolean>
disabled: boolean
/**
* 将控件设置为失去焦点状态
* 将控件设置为 blurred 状态
*/
markAsBlurred: () => void
/**
* 修改控件的值
* 设置控件的值
*/
setValue: (value: T) => void
}

```

## FAQ

### 更多的使用示例和场景?

参见 [@idux/components/form](https://idux.site/components/form/zh)

### 更多的使用细节和文档?

参见 [@angular/forms](https://angular.cn/guide/forms-overview)
Loading