Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPS Next #43

Open
selvagsz opened this issue Apr 9, 2018 · 1 comment
Open

RPS Next #43

selvagsz opened this issue Apr 9, 2018 · 1 comment

Comments

@selvagsz
Copy link
Owner

selvagsz commented Apr 9, 2018

Problem

We've quite a few problems with the current implementation of RPS

  1. 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 like invoice.status === 'void. Same applies for optgroup.

  2. Another main problem is generating a uuid while rendering the options list Fix indexed keys while rendering the Options  #17 . Right now, the key is index-based which is an anti-pattern. I could foresee 2 options to solve this problem
    a. introduce optionValuePath. (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 🎉

@selvagsz
Copy link
Owner Author

selvagsz commented May 3, 2018

Seems like we need to add optionValuePath option even in this approach

Updated the code in the issue description ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant