options 支持配置 selectFirst 自动选择第一个

This commit is contained in:
2betop 2020-12-21 15:30:57 +08:00
parent fbdc573f4b
commit 47b0b5a1de
5 changed files with 103 additions and 13 deletions

View File

@ -274,6 +274,36 @@ order: 2
上例我们设置默认值为`b`,则会自动匹配到选项`B`并选中。
如果想默认选择第一个,可以直接配置 `selectFirst` 属性。
```schema:height="260" scope="body"
{
"type": "form",
"controls": [
{
"label": "选项",
"type": "select",
"name": "select",
"selectFirst": true,
"options": [
{
"label":"A",
"value":"a"
},
{
"label":"B",
"value":"b"
},
{
"label":"C",
"value":"c"
}
]
}
]
}
```
### 动态配置
有时候我们想默认选中一个选项,但是`options`又是远程拉取的,无法确定默认值是啥,这时候,**需要在`source`接口中返回`value`,来动态设置默认值****接口返回数据结构**如下:

View File

@ -77,7 +77,7 @@ export default class FormControl extends React.PureComponent<
trailing: true,
leading: false
});
state = {value: this.value = this.props.control.value};
state = {value: (this.value = this.props.control.value)};
componentWillMount() {
const {
formStore: form,
@ -96,7 +96,8 @@ export default class FormControl extends React.PureComponent<
valueField,
labelField,
joinValues,
extractValue
extractValue,
selectFirst
}
} = this.props;
@ -134,7 +135,8 @@ export default class FormControl extends React.PureComponent<
valueField,
labelField,
joinValues,
extractValue
extractValue,
selectFirst
});
if (this.model.unique && form.parentStore?.storeType === ComboStore.name) {
@ -144,11 +146,11 @@ export default class FormControl extends React.PureComponent<
// 同步 value
this.setState({
value: this.value = model.value
value: (this.value = model.value)
});
this.reaction = reaction(
() => model.value,
value => this.setState({value: this.value = value})
value => this.setState({value: (this.value = value)})
);
}
@ -368,7 +370,7 @@ export default class FormControl extends React.PureComponent<
}
this.setState({
value: this.value = value
value: (this.value = value)
});
changeImmediately || conrolChangeImmediately || !formInited
? this.emitChange(submitOnChange)

View File

@ -58,6 +58,11 @@ export interface FormOptionsControl extends FormBaseControl {
*/
source?: SchemaApi | SchemaTokenizeableString;
/**
*
*/
selectFirst?: boolean;
/**
* source
*
@ -270,7 +275,8 @@ export function registerOptionsControl(config: OptionsConfig) {
formInited,
valueField,
options,
value
value,
selectFirst
} = this.props;
if (formItem) {
@ -298,6 +304,21 @@ export function registerOptionsControl(config: OptionsConfig) {
);
}
// 默认选择第一个
if (
formItem &&
selectFirst &&
formItem.options.length &&
!formItem.selectedOptions.length
) {
const list = extractValue
? formItem.options.map(
(selectedOption: Option) => selectedOption[valueField || 'value']
)
: formItem.options;
setPrinstineValue(multiple ? list.slice(0, 1) : list[0]);
}
loadOptions &&
config.autoLoadOptionsFromSource !== false &&
(formInited
@ -357,10 +378,11 @@ export function registerOptionsControl(config: OptionsConfig) {
props.data,
'| raw'
);
prevOptions !== options &&
formItem.setOptions(normalizeOptions(options || []));
this.normalizeValue();
if (prevOptions !== options) {
formItem.setOptions(normalizeOptions(options || []));
this.normalizeValue();
}
} else if (
isEffectiveApi(props.source, props.data) &&
isApiOutdated(
@ -564,7 +586,7 @@ export function registerOptionsControl(config: OptionsConfig) {
@autobind
reloadOptions(setError?: boolean) {
const {source, formItem, data, onChange} = this.props;
const {source, formItem, data, onChange, selectFirst} = this.props;
if (formItem && isPureVariable(source as string)) {
formItem.setOptions(
@ -572,6 +594,16 @@ export function registerOptionsControl(config: OptionsConfig) {
resolveVariableAndFilter(source as string, data, '| raw') || []
)
);
// 默认选中第一个。
if (
selectFirst &&
formItem.options.length &&
!formItem.selectedOptions.length
) {
this.handleToggle(formItem.options[0], false, true);
}
return;
} else if (!formItem || !isEffectiveApi(source, data)) {
return;

View File

@ -1351,7 +1351,8 @@ export default class Form extends React.Component<FormProps, object> {
classnames: cx,
affixFooter,
lazyLoad,
translate: __
translate: __,
footer
} = this.props;
// trace(true);
@ -1375,6 +1376,7 @@ export default class Form extends React.Component<FormProps, object> {
disabled: store.loading,
btnDisabled: store.loading || store.validating,
headerClassName,
footer,
footerClassName,
actionsClassName,
bodyClassName,

View File

@ -69,6 +69,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
extractValue: false,
options: types.optional(types.array(types.frozen()), []),
expressionsInOptions: false,
selectFirst: false,
selectedOptions: types.optional(types.frozen(), []),
filteredOptions: types.optional(types.frozen(), []),
dialogSchema: types.frozen(),
@ -221,7 +222,8 @@ export const FormItemStore = StoreNode.named('FormItemStore')
joinValues,
extractValue,
type,
id
id,
selectFirst
}: {
required?: any;
unique?: any;
@ -236,6 +238,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
extractValue?: boolean;
type?: string;
id?: string;
selectFirst?: boolean;
}) {
if (typeof rules === 'string') {
rules = str2rules(rules);
@ -247,6 +250,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
typeof required !== 'undefined' && (self.required = !!required);
typeof unique !== 'undefined' && (self.unique = !!unique);
typeof multiple !== 'undefined' && (self.multiple = !!multiple);
typeof selectFirst !== 'undefined' && (self.selectFirst = !!selectFirst);
typeof joinValues !== 'undefined' && (self.joinValues = !!joinValues);
typeof extractValue !== 'undefined' &&
(self.extractValue = !!extractValue);
@ -479,6 +483,26 @@ export const FormItemStore = StoreNode.named('FormItemStore')
if (json.data && typeof (json.data as any).value !== 'undefined') {
onChange && onChange((json.data as any).value, false, true);
} else if (
self.selectFirst &&
self.options.length &&
!self.selectedOptions.length
) {
onChange &&
onChange(
self.options
.slice(0, 1)
.map(item => {
if (self.extractValue || self.joinValues) {
return item.value;
}
return item;
})
[self.joinValues ? 'join' : 'concat'](),
false,
true
);
} else if (clearValue) {
self.selectedOptions.some((item: any) => item.__unmatched) &&
onChange &&