feat(form): add show-label prop (#865)

* feat(form): add show-label prop and test (#858)

* docs(form): add show-label doc and fix form item label desc (#858)

* Update CHANGELOG.en-US.md

Co-authored-by: Yugang Cao <34439652+Talljack@users.noreply.github.com>

* Update CHANGELOG.zh-CN.md

Co-authored-by: Yugang Cao <34439652+Talljack@users.noreply.github.com>

* feat(form): rewrite show-label and add tests (#858)

* docs(form): add show-label demo (#858)

* feat(form): change show-label computed  (#858)

* feat(form): fix show-label (#858)

* feat(form): fix bug (#858)

* feat(form): update show-label scripts (#858)

* docs(form): update show-label order and label description (#858)

* Apply suggestions from code review

Co-authored-by: kev1nzh <kev1nzh@app-ark.com>
Co-authored-by: Yugang Cao <34439652+Talljack@users.noreply.github.com>
Co-authored-by: kev1nzh_ark <kevin@app-ark.com>
Co-authored-by: 07akioni <07akioni2@gmail.com>
This commit is contained in:
Kev1nzh 2021-08-20 01:39:44 +08:00 committed by GitHub
parent 19282b6d56
commit b401ff4793
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 184 additions and 6 deletions

View File

@ -9,6 +9,7 @@
### Feats
- `n-input-number` add `clearable` prop.
- `n-form` add `show-label` prop, closes [#858](https://github.com/TuSimple/naive-ui/issues/858).
## 2.16.4 (2021-08-16)
@ -24,6 +25,7 @@
### Feats
- `n-message-provider` add `container-style` prop
- `n-message-provider` add `container-style` prop.
- `n-message-provider` add `placement` prop.
- `n-message` add class to distinguish type.

View File

@ -9,6 +9,7 @@
### Feats
- `n-input-number` 新增 `clearable` 属性
- `n-form` 新增 `show-label` 属性,关闭 [#858](https://github.com/TuSimple/naive-ui/issues/858)
## 2.16.4 (2021-08-16)

View File

@ -15,6 +15,7 @@ left
item-only
async
disabled
show-label
```
## Props
@ -31,6 +32,7 @@ disabled
| model | `Object` | `{}` | The object to get collected value from form items. |
| rules | `type FormRules = { [itemValidatePath: string]: FormItemRule \| Array<FormItemRule> \| FormRules }` | `{}` | The rules to validate form items. |
| show-feedback | `boolean` | `true` | Whether to show feedback. |
| show-label | `boolean` | `true` | Whether to show label. |
| show-require-mark | `'left' \| 'right' \| 'boolean'` | `'right'` | Whether to show require mark when form item is required. |
| size | `'small' \| 'medium' \| 'large'` | `'medium'` | Size. |
@ -51,7 +53,7 @@ disabled
| feedback | `string` | `undefined` | The feedback message of the form item. If not set to `undefined`, it will take place of the result of rule-based validation. |
| first | `boolean` | `false` | Whether only to show the first validation error message. |
| ingore-path-change | `boolean` | `false` | Usually, the change of `path` will cause the data source's variation. So naive-ui will clear the validation result. If it is not expected, you can set it to `true` |
| label | `string` | `undefined` | Lbale information. |
| label | `string` | `undefined` | Label information. |
| label-align | `'left' \| 'right'` | `undefined` | Text align in label. If not set, use `label-align` from wrapper form. |
| label-placement | `'left' \| 'top'` | `undefined` | If not set, use `label-placement` from wrapper form. |
| label-style | `Object` | `{}` | Label style. |
@ -61,6 +63,7 @@ disabled
| rule | `FormItemRule \| Array<FormItemRule>` | `undefined` | The rule to validate the form item. It will be merged with the rules acquired by `rule-path` from wrapper form's rules. It's recommend to set all rules on wrapper form. |
| rule-path | `string` | `undefined` | The path to get rule from wrapper form's rule object. If not set, use path of the form item instead. |
| show-feedback | `boolean` | `true` | Whether to show feedback. |
| show-label | `boolean` | `true` | Whether to show label. If not set, use `show-label` from wrapper form. |
| show-require-mark | `'left' \| 'right' \| 'boolean'` | `'right'` | Whether to show require mark. If not set, use `show-require-mark` from wrapper form. |
| size | `'small' \| 'medium' \| 'large'` | `'medium'` | Size. |
| validation-status | `'error' \| 'success' \| 'warning'` | `undefined` | The validation status of the form item. If not set to `undefined`, it will take place of the result of rule-based validation. |

View File

@ -0,0 +1,55 @@
# Show/hide Label
`show-label`: When the value is `false`, the `label` element and placeholder for `n-form-item` will be hidden.
`n-form-item` will use the `show-label` of the enclosing `n-form` if it is not set, or default to `true` if neither is set.
```html
<div :style="switchStyle">
<label>n-form</label>
<n-switch v-model:value="formShowLabel" />
</div>
<div :style="switchStyle">
<label>n-form-item</label>
<n-switch v-model:value="formItemShowLabel" />
</div>
<n-form :model="formValue" ref="formRef" :show-label="formShowLabel">
<n-form-item label="Name" path="user.name" :show-label="formItemShowLabel">
<n-input v-model:value="formValue.user.name" placeholder="Input Name" />
</n-form-item>
<n-form-item label="Age" path="user.age">
<n-input placeholder="Input Age" v-model:value="formValue.user.age" />
</n-form-item>
<n-form-item label="Phone" path="user.phone">
<n-input placeholder="Input Phone" v-model:value="formValue.phone" />
</n-form-item>
</n-form>
```
```js
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
const formRef = ref(null)
const formShowLabel = ref(true)
const formItemShowLabel = ref(true)
return {
formRef,
formValue: ref({
user: {
name: '',
age: ''
},
phone: ''
}),
formShowLabel,
formItemShowLabel,
switchStyle: {
marginBottom: '12px'
}
}
}
})
```

View File

@ -17,6 +17,7 @@ async
disabled
height-debug
validator-debug
show-label
```
## Props
@ -33,6 +34,7 @@ validator-debug
| model | `Object` | `{}` | 获取表项中收集到的值的对象 |
| rules | `type FormRules = { [itemValidatePath: string]: FormItemRule \| Array<FormItemRule> \| FormRules }` | `{}` | 验证表项的规则 |
| show-feedback | `boolean` | `true` | 是否展示校验反馈 |
| show-label | `boolean` | `true` | 是否展示标签 |
| show-require-mark | `'left' \| 'right' \| 'boolean'` | `'right'` | 是否展示必填的星号 |
| size | `'small' \| 'medium' \| 'large'` | `'medium'` | 尺寸 |
@ -62,6 +64,7 @@ validator-debug
| rule | `FormItemRule \| Array<FormItemRule>` | `undefined` | 验证表项的规则,它会被通过 `rule-path` 从外层表单获取的规则合并来作为表项的验证规则。推荐还是在外层表单设置所有规则 |
| rule-path | `string` | `undefined` | 从外层表单的 `rules` 对象获取规则的路径。如果没有设定,使用表项的 `path` 代替 |
| show-feedback | `boolean` | `true` | 是否展示校验反馈 |
| show-label | `boolean` | `true` | 是否展示标签。如果没有被设定,使用外层 `n-form``show-label` |
| show-require-mark | `'left' \| 'right' \| 'boolean'` | `'right'` | 是否展示必填的星号。如果没有被设定,使用外层 `n-form``show-require-mark` |
| size | `'small' \| 'medium' \| 'large'` | `'medium'` | 尺寸 |
| validation-status | `'error' \| 'success' \| 'warning'` | `undefined` | 表单的验证状态。不设为 `undefined`时,会覆盖规则验证的结果 |

View File

@ -0,0 +1,55 @@
# 显示/隐藏标签
`show-label`: 当值为 `false` 时,会隐藏 `n-form-item``label` 元素和占位。
`n-form-item` 若未被设定,则会使用外层 `n-form``show-label`, 若都未被设定,则默认为 `true`
```html
<div :style="switchStyle">
<label>n-form</label>
<n-switch v-model:value="formShowLabel" />
</div>
<div :style="switchStyle">
<label>n-form-item</label>
<n-switch v-model:value="formItemShowLabel" />
</div>
<n-form :model="formValue" ref="formRef" :show-label="formShowLabel">
<n-form-item label="姓名" path="user.name" :show-label="formItemShowLabel">
<n-input v-model:value="formValue.user.name" placeholder="输入姓名" />
</n-form-item>
<n-form-item label="年龄" path="user.age">
<n-input placeholder="输入年龄" v-model:value="formValue.user.age" />
</n-form-item>
<n-form-item label="电话号码" path="user.phone">
<n-input placeholder="电话号码" v-model:value="formValue.phone" />
</n-form-item>
</n-form>
```
```js
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
const formRef = ref(null)
const formShowLabel = ref(true)
const formItemShowLabel = ref(true)
return {
formRef,
formValue: ref({
user: {
name: '',
age: ''
},
phone: ''
}),
formShowLabel,
formItemShowLabel,
switchStyle: {
marginBottom: '12px'
}
}
}
})
```

View File

@ -48,6 +48,10 @@ const formProps = {
onSubmit: {
type: Function as PropType<(e: Event) => void>,
default: (e: Event) => e.preventDefault()
},
showLabel: {
type: Boolean as PropType<boolean | undefined>,
default: undefined
}
} as const

View File

@ -52,7 +52,7 @@ import {
export const formItemProps = {
...(useTheme.props as ThemeProps<FormTheme>),
label: {
type: [String, Boolean] as PropType<string | false | undefined>,
type: String as PropType<string | undefined>,
default: undefined
},
labelWidth: [Number, String] as PropType<string | number>,
@ -84,7 +84,11 @@ export const formItemProps = {
default: false
},
validationStatus: String as PropType<'error' | 'warning' | 'success'>,
feedback: String
feedback: String,
showLabel: {
type: Boolean as PropType<boolean | undefined>,
default: undefined
}
} as const
export type FormItemSetupProps = ExtractPropTypes<typeof formItemProps>
@ -412,11 +416,11 @@ export default defineComponent({
`${mergedClsPrefix}-form-item`,
`${mergedClsPrefix}-form-item--${this.mergedSize}-size`,
`${mergedClsPrefix}-form-item--${this.mergedLabelPlacement}-labelled`,
this.label === false && `${mergedClsPrefix}-form-item--no-label`
!this.mergedShowLabel && `${mergedClsPrefix}-form-item--no-label`
]}
style={this.cssVars as CSSProperties}
>
{this.label || $slots.label ? (
{this.mergedShowLabel && (this.label || $slots.label) ? (
<label
class={`${mergedClsPrefix}-form-item-label`}
style={this.mergedLabelStyle as any}

View File

@ -72,6 +72,12 @@ export function formItemMisc (props: FormItemSetupProps) {
if (NForm?.showFeedback !== undefined) return NForm.showFeedback
return true
})
const mergedShowLabelRef = computed(() => {
const { showLabel } = props
if (showLabel !== undefined) return showLabel
if (NForm?.showLabel !== undefined) return NForm.showLabel
return true
})
return {
validationErrored: validationErroredRef,
mergedLabelStyle: mergedLabelStyleRef,
@ -79,7 +85,8 @@ export function formItemMisc (props: FormItemSetupProps) {
mergedLabelAlign: mergedLabelAlignRef,
mergedShowRequireMark: mergedShowRequireMarkRef,
mergedValidationStatus: mergedValidationStatusRef,
mergedShowFeedback: mergedShowFeedbackRef
mergedShowFeedback: mergedShowFeedbackRef,
mergedShowLabel: mergedShowLabelRef
}
}

View File

@ -89,4 +89,48 @@ describe('n-form', () => {
)
})
})
it('should work with `show-label` prop', async () => {
let wrapper = mount(NForm, {
slots: {
default: () =>
[1, 2, 3].map((num) => (
<NFormItem label={`label${num}`}>
{{
default: () => <NInput />
}}
</NFormItem>
))
}
})
// show-label default is true in component
expect(wrapper.findAll('.n-form-item-label').length).toBe(3)
expect(wrapper.findAll('.n-form-item--no-label').length).toBe(0)
await wrapper.setProps({ showLabel: true })
expect(wrapper.findAll('.n-form-item-label').length).toBe(3)
expect(wrapper.findAll('.n-form-item--no-label').length).toBe(0)
await wrapper.setProps({ showLabel: false })
expect(wrapper.findAll('.n-form-item-label').length).toBe(0)
expect(wrapper.findAll('.n-form-item--no-label').length).toBe(3)
// The NFormItem show-label has a higher weight than the NForm
wrapper = mount(NForm, {
props: { showLabel: true },
slots: {
default: () => (
<NFormItem label="label" show-label={false}>
{{
default: () => <NInput />
}}
</NFormItem>
)
}
})
expect(
wrapper.find('.n-form-item').classes().includes('n-form-item--no-label')
).toBe(true)
expect(wrapper.findAll('.n-form-item-label').length).toBe(0)
})
})