diff --git a/src/renderers/Form/Options.tsx b/src/renderers/Form/Options.tsx index 7cacd0c6..7625f840 100644 --- a/src/renderers/Form/Options.tsx +++ b/src/renderers/Form/Options.tsx @@ -106,745 +106,732 @@ export const detectProps = itemDetectProps.concat([ 'extractValue' ]); -export function asOptionsControl(config: OptionsConfig) { - return function (Control: React.ComponentType) { - return class FormOptionsItem extends React.Component { - static displayName = `OptionsControl(${config.type})`; - static defaultProps = { - delimiter: ',', - labelField: 'label', - valueField: 'value', - joinValues: true, - extractValue: false, - multiple: false, - placeholder: '请选择', - resetValue: '', - deleteConfirmText: '确定要删除?', - ...Control.defaultProps - }; - static propsList: any = (Control as any).propsList - ? [...(Control as any).propsList] - : []; - static ComposedComponent = Control; +export function registerOptionsControl(config: OptionsConfig) { + const Control = config.component; - reaction?: () => void; - input: any; + class FormOptionsItem extends React.Component { + static displayName = `OptionsControl(${config.type})`; + static defaultProps = { + delimiter: ',', + labelField: 'label', + valueField: 'value', + joinValues: true, + extractValue: false, + multiple: false, + placeholder: '请选择', + resetValue: '', + deleteConfirmText: '确定要删除?', + ...Control.defaultProps + }; + static propsList: any = (Control as any).propsList + ? [...(Control as any).propsList] + : []; + static ComposedComponent = Control; - componentWillMount() { - const { - initFetch, - formItem, - source, - data, - setPrinstineValue, - defaultValue, - multiple, - joinValues, - extractValue, - addHook, - formInited, - valueField, - options, - value - } = this.props; + reaction?: () => void; + input: any; - if (formItem) { - formItem.setOptions(normalizeOptions(options)); + componentWillMount() { + const { + initFetch, + formItem, + source, + data, + setPrinstineValue, + defaultValue, + multiple, + joinValues, + extractValue, + addHook, + formInited, + valueField, + options, + value + } = this.props; - this.reaction = reaction( - () => JSON.stringify([formItem.loading, formItem.filteredOptions]), - () => this.forceUpdate() - ); - } + if (formItem) { + formItem.setOptions(normalizeOptions(options)); - let loadOptions: boolean = initFetch !== false; - - if (formItem && joinValues === false && defaultValue) { - const selectedOptions = extractValue - ? formItem - .getSelectedOptions(value) - .map( - (selectedOption: Option) => - selectedOption[valueField || 'value'] - ) - : formItem.getSelectedOptions(value); - setPrinstineValue( - multiple ? selectedOptions.concat() : selectedOptions[0] - ); - } - - loadOptions && - config.autoLoadOptionsFromSource !== false && - (formInited - ? this.reload() - : addHook && addHook(this.initOptions, 'init')); + this.reaction = reaction( + () => JSON.stringify([formItem.loading, formItem.filteredOptions]), + () => this.forceUpdate() + ); } - componentDidMount() { + let loadOptions: boolean = initFetch !== false; + + if (formItem && joinValues === false && defaultValue) { + const selectedOptions = extractValue + ? formItem + .getSelectedOptions(value) + .map( + (selectedOption: Option) => + selectedOption[valueField || 'value'] + ) + : formItem.getSelectedOptions(value); + setPrinstineValue( + multiple ? selectedOptions.concat() : selectedOptions[0] + ); + } + + loadOptions && + config.autoLoadOptionsFromSource !== false && + (formInited + ? this.reload() + : addHook && addHook(this.initOptions, 'init')); + } + + componentDidMount() { + this.normalizeValue(); + } + + shouldComponentUpdate(nextProps: OptionsProps) { + if (config.strictMode === false || nextProps.strictMode === false) { + return true; + } else if (nextProps.source || nextProps.autoComplete) { + return true; + } + + if (anyChanged(detectProps, this.props, nextProps)) { + return true; + } + + return false; + } + + componentDidUpdate(prevProps: OptionsProps) { + const props = this.props; + const formItem = props.formItem as IFormItemStore; + + if (!formItem || !props.formInited) { + return; + } else if (!prevProps.formItem) { + // todo 优化 name 变化情况。 + } + + if (prevProps.value !== props.value || formItem.expressionsInOptions) { + formItem.syncOptions(); + } + + if (prevProps.options !== props.options && formItem) { + formItem.setOptions(normalizeOptions(props.options || [])); this.normalizeValue(); - } + } else if ( + config.autoLoadOptionsFromSource !== false && + props.source && + formItem && + (prevProps.source !== props.source || prevProps.data !== props.data) + ) { + if (isPureVariable(props.source as string)) { + const prevOptions = resolveVariableAndFilter( + prevProps.source as string, + prevProps.data, + '| raw' + ); + const options = resolveVariableAndFilter( + props.source as string, + props.data, + '| raw' + ); + prevOptions !== options && + formItem.setOptions(normalizeOptions(options || [])); - shouldComponentUpdate(nextProps: OptionsProps) { - if (config.strictMode === false || nextProps.strictMode === false) { - return true; - } else if (nextProps.source || nextProps.autoComplete) { - return true; - } - - if (anyChanged(detectProps, this.props, nextProps)) { - return true; - } - - return false; - } - - componentDidUpdate(prevProps: OptionsProps) { - const props = this.props; - const formItem = props.formItem as IFormItemStore; - - if (!formItem || !props.formInited) { - return; - } else if (!prevProps.formItem) { - // todo 优化 name 变化情况。 - } - - if (prevProps.value !== props.value || formItem.expressionsInOptions) { - formItem.syncOptions(); - } - - if (prevProps.options !== props.options && formItem) { - formItem.setOptions(normalizeOptions(props.options || [])); this.normalizeValue(); } else if ( - config.autoLoadOptionsFromSource !== false && - props.source && - formItem && - (prevProps.source !== props.source || prevProps.data !== props.data) - ) { - if (isPureVariable(props.source as string)) { - const prevOptions = resolveVariableAndFilter( - prevProps.source as string, - prevProps.data, - '| raw' - ); - const options = resolveVariableAndFilter( - props.source as string, - props.data, - '| raw' - ); - prevOptions !== options && - formItem.setOptions(normalizeOptions(options || [])); - - this.normalizeValue(); - } else if ( - isEffectiveApi(props.source, props.data) && - isApiOutdated( - prevProps.source, - props.source, - prevProps.data, - props.data - ) - ) { - formItem - .loadOptions( - props.source, - props.data, - undefined, - true, - props.onChange - ) - .then(() => this.normalizeValue()); - } - } - } - - componentWillUnmount() { - this.props.removeHook && this.props.removeHook(this.reload, 'init'); - this.reaction && this.reaction(); - } - - normalizeValue() { - const { - joinValues, - extractValue, - value, - multiple, - formItem, - valueField - } = this.props; - - if (!formItem || joinValues !== false || !formItem.options.length) { - return; - } - - if ( - extractValue === false && - (typeof value === 'string' || typeof value === 'number') - ) { - const selectedOptions = formItem.getSelectedOptions(value); - formItem.changeValue( - multiple ? selectedOptions.concat() : selectedOptions[0] - ); - } else if ( - extractValue === true && - value && - !( - (Array.isArray(value) && - value.every( - val => typeof val === 'string' || typeof val === 'number' - )) || - typeof value === 'string' || - typeof value === 'number' + isEffectiveApi(props.source, props.data) && + isApiOutdated( + prevProps.source, + props.source, + prevProps.data, + props.data ) ) { - const selectedOptions = formItem - .getSelectedOptions(value) - .map( - (selectedOption: Option) => selectedOption[valueField || 'value'] - ); - formItem.changeValue( - multiple ? selectedOptions.concat() : selectedOptions[0] - ); - } - } - - getWrappedInstance() { - return this.input; - } - - @autobind - inputRef(ref: any) { - this.input = ref; - } - - @autobind - handleToggle( - option: Option, - submitOnChange?: boolean, - changeImmediately?: boolean - ) { - const { - onChange, - joinValues, - extractValue, - valueField, - delimiter, - clearable, - resetValue, - multiple, - formItem, - value - } = this.props; - - if (!formItem) { - return; - } - - let valueArray = formItem.getSelectedOptions(value).concat(); - const idx = findIndex( - valueArray, - optionValueCompare( - option[valueField || 'value'], - valueField || 'value' - ) - ); - let newValue: string | Array