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

Commit 08bb14b

Browse files
authored
feat(select): add feedbck for select component (#690)
1 parent 7337223 commit 08bb14b

3 files changed

Lines changed: 83 additions & 31 deletions

File tree

src/components/Select/Select.tsx

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import { Typeahead } from 'react-bootstrap-typeahead'
33
import 'react-bootstrap-typeahead/css/Typeahead.css'
4+
import Form from 'react-bootstrap/Form'
45

56
interface SelectOption<T> {
67
label: string
@@ -15,7 +16,9 @@ interface Props<T> {
1516
placeholder?: string
1617
multiple?: boolean
1718
disabled?: boolean
19+
isValid?: boolean
1820
isInvalid?: boolean
21+
feedback?: string
1922
}
2023

2124
function Select<T>(props: Props<T>) {
@@ -27,42 +30,55 @@ function Select<T>(props: Props<T>) {
2730
placeholder,
2831
multiple,
2932
disabled,
33+
isValid,
3034
isInvalid,
35+
feedback,
3136
} = props
3237

3338
return (
34-
<Typeahead<SelectOption<T>>
35-
id={id}
36-
options={options as any}
37-
selected={defaultSelected}
38-
onChange={(selected: SelectOption<T>[]) => {
39-
if (onChange !== undefined) {
40-
onChange(selected.map((option) => option.value))
41-
}
42-
}}
43-
placeholder={placeholder}
44-
multiple={multiple}
45-
disabled={disabled}
46-
isInvalid={isInvalid}
47-
filterBy={(option: SelectOption<T>, selectProps: any) => {
48-
// per https://github.com/HospitalRun/components/issues/517
49-
// change component default behavior
50-
// multiple - filter-out current selections
51-
const isMatch = option.label.toLowerCase().indexOf(selectProps.text.toLowerCase()) !== -1
52-
if (selectProps.selected.length && selectProps.multiple) {
53-
return selectProps.selected.every(
54-
(selected: any) => selected.label !== option.label && isMatch,
55-
)
56-
}
57-
// single (custom)- display all options
58-
if (selectProps.selected.length) {
59-
return true
60-
}
61-
// default filter as normal
39+
<>
40+
<Typeahead<SelectOption<T>>
41+
id={id}
42+
options={options as any}
43+
selected={defaultSelected}
44+
onChange={(selected: SelectOption<T>[]) => {
45+
if (onChange !== undefined) {
46+
onChange(selected.map((option) => option.value))
47+
}
48+
}}
49+
placeholder={placeholder}
50+
multiple={multiple}
51+
disabled={disabled}
52+
isInvalid={isInvalid}
53+
filterBy={(option: SelectOption<T>, selectProps: any) => {
54+
// per https://github.com/HospitalRun/components/issues/517
55+
// change component default behavior
56+
// multiple - filter-out current selections
57+
const isMatch = option.label.toLowerCase().indexOf(selectProps.text.toLowerCase()) !== -1
58+
if (selectProps.selected.length && selectProps.multiple) {
59+
return selectProps.selected.every(
60+
(selected: any) => selected.label !== option.label && isMatch,
61+
)
62+
}
63+
// single (custom)- display all options
64+
if (selectProps.selected.length) {
65+
return true
66+
}
67+
// default filter as normal
6268

63-
return isMatch
64-
}}
65-
/>
69+
return isMatch
70+
}}
71+
/>
72+
<div className={isValid ? 'is-valid' : isInvalid ? 'is-invalid' : undefined} />
73+
<Form.Control.Feedback
74+
className={`text-left ml-3 mt-1 text-small ${
75+
isValid ? 'text-success' : isInvalid ? 'text-danger' : undefined
76+
}`}
77+
type={isValid ? 'valid' : 'invalid'}
78+
>
79+
{feedback}
80+
</Form.Control.Feedback>
81+
</>
6682
)
6783
}
6884

stories/select.stories.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,29 @@ storiesOf('Select', module)
7373
/>
7474
</div>
7575
))
76+
.add('Invalid select with error message', () => (
77+
<div>
78+
<Select
79+
id="select-one"
80+
options={options}
81+
onChange={(selected) => {
82+
Toast('success', 'Selection changed', selected.join(' | '))
83+
}}
84+
isInvalid
85+
feedback="Please select one of the choices"
86+
/>
87+
</div>
88+
))
89+
.add('Valid select with custom validation message', () => (
90+
<div>
91+
<Select
92+
id="select-one"
93+
options={options}
94+
onChange={(selected) => {
95+
Toast('success', 'Selection changed', selected.join(' | '))
96+
}}
97+
isValid
98+
feedback="This is a custom valid message"
99+
/>
100+
</div>
101+
))

test/select.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { shallow, mount } from 'enzyme'
22
import * as React from 'react'
33
import { Typeahead as BootstrapTypeahead } from 'react-bootstrap-typeahead'
4+
import Form from 'react-bootstrap/Form'
45

56
import { Select } from '../src'
67

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

38+
it('Select display the feedback', () => {
39+
const selectWrapper = shallow(
40+
<Select id="id" options={options} isInvalid feedback="feedback" />,
41+
)
42+
const bootstratFeedback = selectWrapper.find(Form.Control.Feedback)
43+
expect(bootstratFeedback.props().type).toEqual('invalid')
44+
expect(bootstratFeedback.props().children).toEqual('feedback')
45+
})
46+
3747
it('Select renders as invalid when the isInvalid prop is true', () => {
3848
const selectWrapper = shallow(<Select id="id" options={options} isInvalid />)
3949
const bootstratSelect = selectWrapper.find(BootstrapTypeahead)

0 commit comments

Comments
 (0)