React 根据另一个下拉选择值选择链式选项
Posted
技术标签:
【中文标题】React 根据另一个下拉选择值选择链式选项【英文标题】:React Select chained options based on another dropdown selected value 【发布时间】:2020-07-11 03:34:42 【问题描述】:使用 React Select Async 链接选项的最佳实践是什么。
我的意思是:我有 3 个下拉菜单,第一个是使用选项值从默认值填充的,接下来的 2 个下拉菜单被禁用。
选择第一个下拉值应根据其值填充第二个下拉选项,依此类推,下一个下拉列表。
所以我一直在尝试
import React from "react";
import Select from "react-select";
import AsyncSelect from "react-select/async";
import classnames from "classnames";
import Requests from "../services/requests";
const filterOptions = (inputValue, options) =>
return options.filter(i =>
i.label.toLowerCase().includes(inputValue.toLowerCase())
);
;
class FieldsRenderer extends React.Component
constructor(props)
super(props);
this.state =
fields: props.fields,
containerClass: props.containerClass,
stepSnapshot: null,
selectOptions:
;
this.props.fields.map( (f) =>
if(f.type === 'select' && typeof f.dependsOn !== 'undefined')
this.state.selectOptions[f.name] = null;
)
static getDerivedStateFromProps(nextProps, prevState)
if (nextProps.fields !== prevState.fields)
return
fields: nextProps.fields,
containerClass: nextProps.containerClass
;
return null;
componentDidUpdate(prevProps, nextProps)
if (prevProps !== this.props)
this.setState(
fields: nextProps.fields,
containerClass: nextProps.containerClass
);
this.props.fields.map(f =>
if (typeof f.dependsOn != "undefined")
this.state.selectOptions[f.name] = null;
);
handleInputChange = (index, e) =>
console.log(e.target.value);
console.log(index);
;
handleSelectChange = (selectedOption, item) =>
this.setState(
stepSnapshot:
[item.name]:
value: selectedOption.value,
label: selectedOption.label
);
let childField = this.props.fields.filter(t =>
if (t.type === "select" && typeof t.dependsOn !== "undefined")
return t.dependsOn === item.name;
);
if (childField)
this.loadChildOptions(childField[0], selectedOption);
;
//load child slect options
loadChildOptions(target, parentValue)
Requests.get(
process.env.REACT_APP_API_BASE_URL +
target.source +
"/" +
parentValue.value,
(status, data) =>
//data will be set but will be shown just the previous state
this.state.selectOptions[target.name] = data;
);
render()
let containerClass = "";
let fields = this.state.fields.map((field, i) =>
const fieldType = field.type;
let fieldStyle;
if (
typeof this.state.containerClass !== "undefined" &&
this.state.containerClass !== ""
)
containerClass = this.state.containerClass;
if (typeof field.width !== "undefined" && field.width !== "")
fieldStyle =
width: "calc(" + field.width + " - 5px)"
;
switch (fieldType)
case "select":
const selectCustomStyles =
control: (base, state) => (
...base,
boxShadow: state.isFocused ? 0 : 0,
borderWidth: 2,
height: 45,
borderColor: state.isFocused ? "#707070" : base.borderColor,
"&:hover":
borderColor: state.isFocused ? "#707070" : base.borderColor
),
option: (provided, state) => (
...provided,
backgroundColor: state.isSelected ? "#46B428" : "initial"
)
;
if (
typeof field.async !== "undefined" &&
typeof field.dependsOn === "undefined"
)
return (
<div key=i className="field-wrapper">
<AsyncSelect
loadOptions=(inputValue, callback) =>
Requests.get(
process.env.REACT_APP_API_BASE_URL + field.source,
(status, data) =>
callback(data);
);
styles=selectCustomStyles
defaultOptions
name=field.name
placeholder=field.label
onChange=this.handleSelectChange
/>
</div>
);
else if(typeof field.dependsOn !== "undefined")
return(<div key=i className="field-wrapper">
<AsyncSelect
styles=selectCustomStyles
placeholder=field.label
defaultOptions=this.state.selectOptions[field.name]
loadOptions=this.state.selectOptions[field.name]
/>
</div>)
else
const disabled =
typeof field.dependsOn !== "undefined" && field.dependsOn !== ""
? this.state.selectOptions[field.name] != null
? false
: true
: false;
return (
<div key=i className="field-wrapper">
<Select
styles=selectCustomStyles
placeholder=field.label
//isLoading=this.state.selectOptions[field.name].length ? true : false
isDisabled=disabled
name=field.name
options=this.state.selectOptions[field.name]
/>
</div>
);
case "input":
let suffix;
let inputAppendClass;
if (typeof field.suffix !== "undefined" && field.suffix !== "")
inputAppendClass = "input-has-append";
suffix = <span className="input-append">field.suffix</span>;
return (
<div
key=i
className=classnames("field-wrapper input", inputAppendClass)
style=fieldStyle
>
<input
placeholder=field.label
type="text"
className="input-field"
onChange=event => this.handleInputChange(field.name, event)
/>
suffix
</div>
);
break;
case "checkbox":
containerClass = "checkbox-fields";
let radios = field.options.map((option, b) =>
return (
<div key=i + b className="field-wrapper checkbox-button">
<input
placeholder=option.label
id=option.name + "_" + i + b
type="checkbox"
className="input-field"
/>
<label htmlFor=option.name + "_" + i + b>
<div className="label-name">option.label</div>
<span className="info-icon"></span>
<div className="hint">option.hint</div>
</label>
</div>
);
);
return radios;
break;
case "radio":
let radios = field.options.map((option, k) =>
return (
<div key=i + k className="field-wrapper radio-button">
<input
name=option.name
id=option.name + "_" + i + k
placeholder=option.label
type="radio"
className="input-field"
/>
<label htmlFor=option.name + "_" + i + k>
<div className="label-name">option.label</div>
<div className="hint">option.hint</div>
</label>
</div>
);
);
return radios;
break;
default:
break;
);
return (
<div className=classnames("fields-group", containerClass)>fields</div>
);
export default FieldsRenderer;
【问题讨论】:
【参考方案1】:例如我有react-select
Async 字段。我用于管理表单formik
。首先你创建字段:
<AsyncSelect
name="first"
...
onChange=(name, value) =>
// you can write what you want but here small example what I do for other
// two fields
setFieldValue('second', null);
setFieldValue('third', null);
return setFieldValue(name, value);
/>
还有second
字段:
<AsyncSelect
name="second"
key=!!values.first && !!values.first.id ? values.first.id : null
...
onChange=(name, value) =>
setFieldValue('third', null);
return setFieldValue(name, value);
/>
我给key
并在更改第一个字段时更改key
值。因为如果你不这样做second
字段不知道first
字段何时更改值。如果你给 uniq 可变 key
秒可以从远程数据加载,这取决于 first
字段。
和third
字段:
<AsyncSelect
name="third"
key=!!values.third && !!values.third.id ? values.third.id : null
...
onChange=setFieldValue
/>
这是管理依赖的三个或更多字段的简单方法。我想你理解这个逻辑。
【讨论】:
以上是关于React 根据另一个下拉选择值选择链式选项的主要内容,如果未能解决你的问题,请参考以下文章
使用 AJAX、PHP 和 MySQL 链式填充 HTML 选择框
django:在管理员中智能选择 ChainedForeignKey / 链式下拉菜单