Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
feat(select): add feedbck for select component (#690)
Browse files Browse the repository at this point in the history
  • Loading branch information
SamuelQZQ authored Feb 4, 2021
1 parent 7337223 commit 08bb14b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 31 deletions.
78 changes: 47 additions & 31 deletions src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import { Typeahead } from 'react-bootstrap-typeahead'
import 'react-bootstrap-typeahead/css/Typeahead.css'
import Form from 'react-bootstrap/Form'

interface SelectOption<T> {
label: string
Expand All @@ -15,7 +16,9 @@ interface Props<T> {
placeholder?: string
multiple?: boolean
disabled?: boolean
isValid?: boolean
isInvalid?: boolean
feedback?: string
}

function Select<T>(props: Props<T>) {
Expand All @@ -27,42 +30,55 @@ function Select<T>(props: Props<T>) {
placeholder,
multiple,
disabled,
isValid,
isInvalid,
feedback,
} = props

return (
<Typeahead<SelectOption<T>>
id={id}
options={options as any}
selected={defaultSelected}
onChange={(selected: SelectOption<T>[]) => {
if (onChange !== undefined) {
onChange(selected.map((option) => option.value))
}
}}
placeholder={placeholder}
multiple={multiple}
disabled={disabled}
isInvalid={isInvalid}
filterBy={(option: SelectOption<T>, selectProps: any) => {
// per https://github.com/HospitalRun/components/issues/517
// change component default behavior
// multiple - filter-out current selections
const isMatch = option.label.toLowerCase().indexOf(selectProps.text.toLowerCase()) !== -1
if (selectProps.selected.length && selectProps.multiple) {
return selectProps.selected.every(
(selected: any) => selected.label !== option.label && isMatch,
)
}
// single (custom)- display all options
if (selectProps.selected.length) {
return true
}
// default filter as normal
<>
<Typeahead<SelectOption<T>>
id={id}
options={options as any}
selected={defaultSelected}
onChange={(selected: SelectOption<T>[]) => {
if (onChange !== undefined) {
onChange(selected.map((option) => option.value))
}
}}
placeholder={placeholder}
multiple={multiple}
disabled={disabled}
isInvalid={isInvalid}
filterBy={(option: SelectOption<T>, selectProps: any) => {
// per https://github.com/HospitalRun/components/issues/517
// change component default behavior
// multiple - filter-out current selections
const isMatch = option.label.toLowerCase().indexOf(selectProps.text.toLowerCase()) !== -1
if (selectProps.selected.length && selectProps.multiple) {
return selectProps.selected.every(
(selected: any) => selected.label !== option.label && isMatch,
)
}
// single (custom)- display all options
if (selectProps.selected.length) {
return true
}
// default filter as normal

return isMatch
}}
/>
return isMatch
}}
/>
<div className={isValid ? 'is-valid' : isInvalid ? 'is-invalid' : undefined} />
<Form.Control.Feedback
className={`text-left ml-3 mt-1 text-small ${
isValid ? 'text-success' : isInvalid ? 'text-danger' : undefined
}`}
type={isValid ? 'valid' : 'invalid'}
>
{feedback}
</Form.Control.Feedback>
</>
)
}

Expand Down
26 changes: 26 additions & 0 deletions stories/select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,29 @@ storiesOf('Select', module)
/>
</div>
))
.add('Invalid select with error message', () => (
<div>
<Select
id="select-one"
options={options}
onChange={(selected) => {
Toast('success', 'Selection changed', selected.join(' | '))
}}
isInvalid
feedback="Please select one of the choices"
/>
</div>
))
.add('Valid select with custom validation message', () => (
<div>
<Select
id="select-one"
options={options}
onChange={(selected) => {
Toast('success', 'Selection changed', selected.join(' | '))
}}
isValid
feedback="This is a custom valid message"
/>
</div>
))
10 changes: 10 additions & 0 deletions test/select.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { shallow, mount } from 'enzyme'
import * as React from 'react'
import { Typeahead as BootstrapTypeahead } from 'react-bootstrap-typeahead'
import Form from 'react-bootstrap/Form'

import { Select } from '../src'

Expand Down Expand Up @@ -34,6 +35,15 @@ describe('Select', () => {
expect(bootstratSelect.props().disabled).toEqual(true)
})

it('Select display the feedback', () => {
const selectWrapper = shallow(
<Select id="id" options={options} isInvalid feedback="feedback" />,
)
const bootstratFeedback = selectWrapper.find(Form.Control.Feedback)
expect(bootstratFeedback.props().type).toEqual('invalid')
expect(bootstratFeedback.props().children).toEqual('feedback')
})

it('Select renders as invalid when the isInvalid prop is true', () => {
const selectWrapper = shallow(<Select id="id" options={options} isInvalid />)
const bootstratSelect = selectWrapper.find(BootstrapTypeahead)
Expand Down

0 comments on commit 08bb14b

Please sign in to comment.