RPS Next
selvagsz opened this issue · comments
Problem
We've quite a few problems with the current implementation of RPS
-
Currently, disabling a particular option is done via
disabled
flag in the option. But, what if you need some conditional logic to disable the option likeinvoice.status === 'void
. Same applies for optgroup. -
Another main problem is generating a uuid while rendering the options list #17 . Right now, the key is index-based which is an anti-pattern. I could foresee 2 options to solve this problem
a. introduceoptionValuePath
.(Unnecessary increase in api surface)
b. implement/use a guuid counter to generate the uuids. (But why when the consumer can dictate the unique field ?)
Proposal
The best option is to offload the looping of options/optgroups to the consumer end like we do for html selects.
In a better world, we can make use of the render props & children as function patterns to achieve the utmost composability without increasing the api surface.
// Basic - Plain Array
<PowerSelect
options={items}
selected={this.state.selectedItem}
onChange={this.handleChange}
>
{
({ results, getOptionProps }) => (
results.map(item => <Option key={item} ...getOptionProps({ option: item })>{item}</Option>)
)
}
</PowerSelect>
// Basic - Array of objects
<PowerSelect
options={items}
selected={this.state.selectedItem}
selectedOptionComponent={({ option }) => option.name}
searchFields={['name']}
onChange={this.handleChange}
>
{
({ results, getOptionProps }) => (
results.map(item => <Option key={item.id} ...getOptionProps({ option: item, disabled: item.status === 'void' })>{item.name}</Option>)
)
}
</PowerSelect>
// OptGroup
<PowerSelect
options={items}
selected={this.state.selectedItem}
selectedOptionComponent={({ option }) => option.name}
searchFields={['name']}
onChange={this.handleChange}
>
{
({ results, getOptionProps, getOptGroupProps }) => (
results.map(item => (
<OptGroup key={item.groupId} ...getOptGroupProps({ label: item.name, disabled: item.continent === 'Asia' })>
{
item.options.map(option => <Option key={option.id} ...getOptionProps({ option: option })>{option.name}</Option>)
}
</OptGroup>
))
)
}
</PowerSelect>
// With all configurations
<PowerSelect
options={items}
selected={this.state.selectedItem}
selectedOptionComponent={({ option }) => option.name}
onChange={this.handleChange}
searchFields={['name']}
selectedOptionComponent={}
triggerLHSComponent={}
triggerRHSComponent={}
beforeOptionsComponent={}
afterOptionsComponent={}
>
{
({ results, getOptionProps }) => (
results.map(item => <Option key={item.id} ...getOptionProps({ option: item, disabled=item.status === 'paid' })>{item.name}</Option>)
)
}
</PowerSelect>
With the above approach, we can deprecate optionLabelPath
, optionComponent
completely thereby achieving more composability with decreased api surface
Seems like we need to add optionValuePath
option even in this approach
Updated the code in the issue description ^^