Skip to content

Commit

Permalink
feat(form): 新增 label-position & star-position (#2659) (#2663)
Browse files Browse the repository at this point in the history
  • Loading branch information
yi-boide authored Dec 4, 2023
1 parent 7330026 commit e24306b
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 13 deletions.
12 changes: 12 additions & 0 deletions packages/nutui-taro-demo/src/dentry/pages/form/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@
></nut-address>
</nut-form-item>
</nut-form>
<h2>自定义labe位置</h2>
<nut-form label-position="top" star-position="right">
<nut-form-item label="姓名" required>
<nut-input v-model="basicData.name" class="nut-input-text" placeholder="请输入姓名" type="text" />
</nut-form-item>
<nut-form-item label="年龄" required>
<nut-input v-model="basicData.age" class="nut-input-text" placeholder="请输入年龄" type="text" />
</nut-form-item>
<nut-form-item label-position="left" label="备注">
<nut-textarea placeholder="请输入备注" type="text" />
</nut-form-item>
</nut-form>
</Demo>
</template>

Expand Down
13 changes: 11 additions & 2 deletions src/packages/__VUE/form/common.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { getPropByPath, isPromise } from '@/packages/utils/util';
import { computed, PropType, provide, reactive, watch } from 'vue';
import { FormItemRule } from '../formitem/types';
import { ErrorMessage, FormRule, FormRules, FORM_KEY } from './types';
import { FORM_KEY } from './types';
import { useChildren } from '@/packages/utils';
import type { FormItemRule } from '../formitem/types';
import type { ErrorMessage, FormRule, FormRules, FormLabelPosition, FormStarPosition } from './types';

export const component = (components: any) => {
return {
Expand All @@ -14,6 +15,14 @@ export const component = (components: any) => {
rules: {
type: Object as PropType<FormRules>,
default: () => ({})
},
labelPosition: {
type: String as PropType<FormLabelPosition>,
default: 'left'
},
starPosition: {
type: String as PropType<FormStarPosition>,
default: 'left'
}
},
components,
Expand Down
18 changes: 16 additions & 2 deletions src/packages/__VUE/form/demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,18 @@
></nut-address>
</nut-form-item>
</nut-form>
<h2>{{ translate('customLabelPosition') }}</h2>
<nut-form label-position="top" star-position="right">
<nut-form-item :label="translate('name')" required>
<nut-input v-model="basicData.name" class="nut-input-text" :placeholder="translate('nameTip')" type="text" />
</nut-form-item>
<nut-form-item :label="translate('age')" required>
<nut-input v-model="basicData.age" class="nut-input-text" :placeholder="translate('ageTip')" type="text" />
</nut-form-item>
<nut-form-item :label="translate('remarks')" label-position="left">
<nut-textarea :placeholder="translate('remarksTip')" type="text" />
</nut-form-item>
</nut-form>
</div>
</template>

Expand Down Expand Up @@ -229,7 +241,8 @@ const translate = useTranslate({
uploader: '文件上传',
success: '上传成功',
uploading: '上传中...',
asyncValidator: '模拟异步验证中'
asyncValidator: '模拟异步验证中',
customLabelPosition: '自定义 label 位置'
},
'en-US': {
basic: 'Basic Usage',
Expand Down Expand Up @@ -268,7 +281,8 @@ const translate = useTranslate({
uploader: 'Upload file',
success: 'Upload successful',
uploading: 'Uploading',
asyncValidator: 'Simulating asynchronous verification'
asyncValidator: 'Simulating asynchronous verification',
customLabelPosition: 'Customize the label location'
}
});
const formData = reactive({
Expand Down
33 changes: 33 additions & 0 deletions src/packages/__VUE/form/doc.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,35 @@ const addressModule = reactive({

:::

### Customize the Label & Star location v4.2.4

:::demo

```vue
<template>
<nut-form label-position="top" star-position="right">
<nut-form-item label="name" required>
<nut-input v-model="basicData.name" class="nut-input-text" placeholder="Please enter your name" type="text" />
</nut-form-item>
<nut-form-item label="age" required>
<nut-input v-model="basicData.age" class="nut-input-text" placeholder="Please enter your age" type="text" />
</nut-form-item>
<nut-form-item label="remark" label-position="left">
<nut-textarea placeholder="Please enter remark" type="text" />
</nut-form-item>
</nut-form>
</template>
<script setup>
import { reactive } from 'vue';
const basicData = reactive({
name: '',
age: ''
});
</script>
```

:::

## API

### Form Props
Expand All @@ -424,6 +453,8 @@ const addressModule = reactive({
| --- | --- | --- | --- |
| model-value | Form data object (required when using form verification) | object | |
| rules | Unified configuration FormItem attr rules | { prop: FormItemRule[] } | `{}` |
| label-position`v4.2.4` | The location of the form item label | `top` \| `left` \| `right` | `left` |
| star-position`v4.2.4` | The red star position of the single label is required | `left` \| `right` | `left` |

### Form Events

Expand All @@ -444,6 +475,8 @@ const addressModule = reactive({
| error-message-align | Error prompt text alignment. The optional values are `center` and `right` | string | `left` |
| show-error-line | Whether to mark the input box in red when the verification fails | boolean | `true` |
| show-error-message | Whether to display the error prompt under the input box when the verification fails | boolean | `true` |
| label-position`v4.2.4` | The location of the form item label, The priority is higher than that in form label-position | `top` \| `left` \| `right` | `left` |
| star-position`v4.2.4` | The red star position of the single label is required, The priority is higher than that in form star-position | `left` \| `right` | `left` |

### FormItemRule data structure

Expand Down
33 changes: 33 additions & 0 deletions src/packages/__VUE/form/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,35 @@ const addressModule = reactive({

:::

### 自定义 Label & Star 位置 v4.2.4

:::demo

```vue
<template>
<nut-form label-position="top" star-position="right">
<nut-form-item label="姓名" required>
<nut-input v-model="basicData.name" class="nut-input-text" placeholder="请输入姓名" type="text" />
</nut-form-item>
<nut-form-item label="年龄" required>
<nut-input v-model="basicData.age" class="nut-input-text" placeholder="请输入年龄" type="text" />
</nut-form-item>
<nut-form-item label="备注" label-position="left">
<nut-textarea placeholder="请输入备注" type="text" />
</nut-form-item>
</nut-form>
</template>
<script setup>
import { reactive } from 'vue';
const basicData = reactive({
name: '',
age: ''
});
</script>
```

:::

## API

### Form Props
Expand All @@ -419,6 +448,8 @@ const addressModule = reactive({
| --- | --- | --- | --- |
| model-value | 表单数据对象(使用表单校验时,_必填_) | object | |
| rules | 统一配置每个 `FormItem``rules` | { prop: FormItemRule[] } | `{}` |
| label-position`v4.2.4` | 表单项 label 的位置 | `top` \| `left` \| `right` | `left` |
| star-position`v4.2.4` | 必填表单项 label 的红色星标位置 | `left` \| `right` | `left` |

### Form Events

Expand All @@ -439,6 +470,8 @@ const addressModule = reactive({
| error-message-align | 错误提示文案对齐方式,可选值为 `center` `right` | string | `left` |
| show-error-line | 是否在校验不通过时标红输入框 | boolean | `true` |
| show-error-message | 是否在校验不通过时在输入框下方展示错误提示 | boolean | `true` |
| label-position`v4.2.4` | 表单项 label 的位置,优先级高于 form 中的 label-position | `top` \| `left` \| `right` | `left` |
| star-position`v4.2.4` | 必填表单项 label 的红色星标位置,优先级高于 form 中的 star-position | `left` \| `right` | `left` |

### FormItemRule 数据结构

Expand Down
33 changes: 33 additions & 0 deletions src/packages/__VUE/form/doc.taro.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,35 @@ const addressModule = reactive({

:::

### 自定义 Label & Star 位置 v4.2.4

:::demo

```vue
<template>
<nut-form label-position="top" star-position="right">
<nut-form-item label="姓名" required>
<nut-input v-model="basicData.name" class="nut-input-text" placeholder="请输入姓名" type="text" />
</nut-form-item>
<nut-form-item label="年龄" required>
<nut-input v-model="basicData.age" class="nut-input-text" placeholder="请输入年龄" type="text" />
</nut-form-item>
<nut-form-item label="备注" label-position="left">
<nut-textarea placeholder="请输入备注" type="text" />
</nut-form-item>
</nut-form>
</template>
<script setup>
import { reactive } from 'vue';
const basicData = reactive({
name: '',
age: ''
});
</script>
```

:::

## API

### Form Props
Expand All @@ -419,6 +448,8 @@ const addressModule = reactive({
| --- | --- | --- | --- |
| model-value | 表单数据对象(使用表单校验时,_必填_) | object | |
| rules | 统一配置每个 `FormItem``rules` | { prop: FormItemRule[] } | `{}` |
| label-position`v4.2.4` | 表单项 label 的位置 | `top` \| `left` \| `right` | `left` |
| star-position`v4.2.4` | 必填表单项 label 的红色星标位置 | `left` \| `right` | `left` |

### Form Events

Expand All @@ -439,6 +470,8 @@ const addressModule = reactive({
| error-message-align | 错误提示文案对齐方式,可选值为 `center` `right` | string | `left` |
| show-error-line | 是否在校验不通过时标红输入框 | boolean | `true` |
| show-error-message | 是否在校验不通过时在输入框下方展示错误提示 | boolean | `true` |
| label-position`v4.2.4` | 表单项 label 的位置,优先级高于 form 中的 label-position | `top` \| `left` \| `right` | `left` |
| star-position`v4.2.4` | 必填表单项 label 的红色星标位置,优先级高于 form 中的 star-position | `left` \| `right` | `left` |

### FormItemRule 数据结构

Expand Down
5 changes: 4 additions & 1 deletion src/packages/__VUE/form/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FormItemRule } from '../formitem/types';
import { FormItemRule, FormItemLabelPosition, FormItemStarPosition } from '../formitem/types';

export const FORM_KEY = Symbol('nut-form');

Expand All @@ -15,3 +15,6 @@ export type ErrorMessage = {
prop: string;
message: string;
};

export type FormLabelPosition = FormItemLabelPosition;
export type FormStarPosition = FormItemStarPosition;
25 changes: 25 additions & 0 deletions src/packages/__VUE/formitem/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@
color: $form-item-required-color;
margin-right: $form-item-required-margin-right;
}
&.nut-form-item__star-right {
&::before {
content: none;
}
&::after {
content: '*';
color: $form-item-required-color;
margin-left: $form-item-required-margin-right;
}
}
}
}
&__body {
Expand Down Expand Up @@ -87,4 +97,19 @@
color: $form-item-error-message-color;
}
}

&__right {
--nut-form-item-label-text-align: right;
}

&__top {
flex-direction: column;
.nut-form-item__label {
padding-bottom: 5px;
width: 100%;
box-sizing: border-box;
display: block;
padding-right: 24px;
}
}
}
37 changes: 33 additions & 4 deletions src/packages/__VUE/formitem/index.taro.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<template>
<nut-cell
class="nut-form-item"
:class="[{ error: parent[prop], line: showErrorLine }, $attrs.class]"
:class="[{ error: parent[prop], line: showErrorLine }, $attrs.class, labelPositionClass]"
:style="$attrs.style"
>
<view
v-if="label || getSlots('label')"
class="nut-cell__title nut-form-item__label"
:style="labelStyle"
:class="{ required: isRequired }"
:class="{ required: isRequired, [starPositionClass]: starPositionClass }"
>
<slot name="label">{{ label }}</slot>
</view>
Expand All @@ -25,7 +25,7 @@
<script lang="ts">
import { pxCheck } from '@/packages/utils/pxCheck';
import { computed, inject, PropType, CSSProperties } from 'vue';
import type { FormItemRule } from './types';
import type { FormItemRule, FormItemLabelPosition, FormItemStarPosition } from './types';
import { createComponent } from '@/packages/utils/create';
import NutCell from '../cell/index.taro.vue';
import { FORM_KEY } from '../form/types';
Expand Down Expand Up @@ -73,6 +73,14 @@ export default create({
bodyAlign: {
type: String,
default: ''
},
labelPosition: {
type: String as PropType<FormItemLabelPosition>,
default: ''
},
starPosition: {
type: String as PropType<FormItemStarPosition>,
default: ''
}
},
components: {
Expand All @@ -91,6 +99,18 @@ export default create({
return props.required || props.rules.some((rule) => rule.required) || formRequired;
});
const labelPositionClass = computed(() => {
const labelPosition = parentObj.props.labelPosition;
const position = props.labelPosition ? props.labelPosition : labelPosition;
return position !== 'left' ? `nut-form-item__${position}` : '';
});
const starPositionClass = computed(() => {
const starPosition = parentObj.props.starPosition;
const position = props.starPosition ? props.starPosition : starPosition;
return position !== 'left' ? `nut-form-item__star-${position}` : '';
});
const parent = inject('formErrorTip') as any;
const labelStyle = computed(() => {
Expand All @@ -110,7 +130,16 @@ export default create({
} as CSSProperties;
});
const getSlots = (name: string) => slots[name];
return { parent, labelStyle, bodyStyle, errorMessageStyle, getSlots, isRequired };
return {
parent,
labelStyle,
bodyStyle,
errorMessageStyle,
getSlots,
isRequired,
labelPositionClass,
starPositionClass
};
}
});
</script>
Loading

0 comments on commit e24306b

Please sign in to comment.