Skip to content

Commit

Permalink
Add shouldFillInputWithSelection prop
Browse files Browse the repository at this point in the history
Co-authored-by: master-elodin <[email protected]>
  • Loading branch information
PatrickDesign and master-elodin committed Oct 3, 2020
1 parent 8da3c9b commit a4ee1d0
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 54 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ keys|all[Array]|List of properties that will be searched. This also supports nes
list|null|Array of properties to be filtered.
placeholder|'Search'|Placeholder of the searchbox
resultsTemplate| Func | Template of the dropdown divs
shouldFillInputWithSelection| false | Determines whether or not to sync the input value with the current selection.
shouldSort| true | Whether to sort the result list, by score.
sortFn|`Array.prototype.sort`|The function that is used for sorting the result list.
threshold|0.6|At what point does the match algorithm give up. A threshold of `0.0` requires a perfect match (of both letters and location), a threshold of `1.0` would match anything.
Expand Down
47 changes: 25 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export default class FuzzySearch extends Component {
location: PropTypes.number,
placeholder: PropTypes.string,
resultsTemplate: PropTypes.func,
shouldFillInputWithSelection: PropTypes.bool,
shouldSort: PropTypes.bool,
sortFn: PropTypes.func,
threshold: PropTypes.number,
Expand All @@ -98,6 +99,7 @@ export default class FuzzySearch extends Component {
width: 430,
placeholder: 'Search',
resultsTemplate: defaultResultsTemplate,
shouldFillInputWithSelection: false,
shouldSort: true,
sortFn(a, b) {
return a.score - b.score;
Expand All @@ -114,7 +116,6 @@ export default class FuzzySearch extends Component {
this.state = {
results: [],
selectedIndex: 0,
selectedValue: {},
value: '',
};
this.handleChange = this.handleChange.bind(this);
Expand Down Expand Up @@ -164,6 +165,27 @@ export default class FuzzySearch extends Component {
});
}

selectItem(index) {
const { results } = this.state;
const { keyForDisplayName, onSelect, shouldFillInputWithSelection } = this.props

const selectedIndex = index || this.state.selectedIndex;
const result = results[selectedIndex];
if (result) {
// send result to onSelectMethod
onSelect(result);
// and set it as input value
this.setState({
value: shouldFillInputWithSelection ? (result[keyForDisplayName] || result) : ''
});
}
// hide dropdown
this.setState({
results: [],
selectedIndex: 0,
});
}

handleKeyDown(e) {
const { results, selectedIndex } = this.state;

Expand All @@ -181,31 +203,12 @@ export default class FuzzySearch extends Component {

// Handle ENTER
} else if (e.keyCode === 13) {
if (results[selectedIndex]) {
this.props.onSelect(results[this.state.selectedIndex]);
this.setState({
selectedValue: results[this.state.selectedIndex],
});
}
this.setState({
results: [],
selectedIndex: 0,
value: results[this.state.selectedIndex].item ? results[this.state.selectedIndex].item.value : '',
});
this.selectItem();
}
}

handleMouseClick(clickedIndex) {
const { results } = this.state;

if (results[clickedIndex]) {
this.props.onSelect(results[clickedIndex]);
}
this.setState({
results: [],
selectedIndex: 0,
value: results[this.state.selectedIndex].item ? results[this.state.selectedIndex].item.value : '',
});
this.selectItem(clickedIndex);
}

render() {
Expand Down
91 changes: 59 additions & 32 deletions src/tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ const list = [
},
];

const triggerDropdown = (wrapper, letter='t') => {
const input = wrapper.find('input');

input.simulate('change', {
target: {
value: letter,
},
});
}

describe('<FuzzySearch />', () => {
it('should set correct placeholder text', () => {
const onSelect = sinon.spy();
Expand All @@ -46,14 +56,9 @@ describe('<FuzzySearch />', () => {
<FuzzySearch onSelect={onSelect} keys={['author', 'title']} list={list} />,
);

const input = wrapper.find('input');
expect(wrapper.state('results').length).to.equal(0);

input.simulate('change', {
target: {
value: 't',
},
});
triggerDropdown(wrapper);

expect(wrapper.state('results').length).to.not.equal(0);
});
Expand All @@ -64,28 +69,18 @@ describe('<FuzzySearch />', () => {
<FuzzySearch list={list} onSelect={onChange} keys={['author', 'title']} id="id" />,
);

const input = wrapper.find('input');
input.simulate('change', {
target: {
value: 't',
},
});
triggerDropdown(wrapper);

expect(wrapper.state('results')).to.eql(['1', '2']);
});

it('should call onChange on selection of result', () => {
it('should call onChange on selection of result and input value set', () => {
const onChange = sinon.spy();
const wrapper = mount(
<FuzzySearch list={list} onSelect={onChange} keys={['author', 'title']} />,
<FuzzySearch list={list} onSelect={onChange} keys={['author', 'title']} shouldFillInputWithSelection/>,
);

const input = wrapper.find('input');
input.simulate('change', {
target: {
value: 't',
},
});
triggerDropdown(wrapper);

expect(wrapper.state('results').length).to.not.equal(0);

Expand All @@ -96,6 +91,28 @@ describe('<FuzzySearch />', () => {
});

expect(onChange.calledOnce).to.equal(true);

// results should be hidden
expect(wrapper.state('results').length).to.equal(0);
// input value should be set
expect(wrapper.find('input').props().value).to.equal('The Great Gatsby');
});

it('should call onSelect on selection of result if mouse clicked', () => {
const onChange = sinon.spy();
const wrapper = mount(
<FuzzySearch list={list} onSelect={onChange} keys={['author', 'title']} />,
);

triggerDropdown(wrapper);

expect(wrapper.state('results').length).to.not.equal(0);

wrapper.find('div[children="The DaVinci Code"]').simulate('click');

expect(onChange.calledOnce).to.equal(true);
// results should be hidden
expect(wrapper.state('results').length).to.equal(0);
});

it('should overwrite previous props with options passed in', () => {
Expand All @@ -109,12 +126,7 @@ describe('<FuzzySearch />', () => {
/>,
);

const input = wrapper.find('input');
input.simulate('change', {
target: {
value: 't',
},
});
triggerDropdown(wrapper);

// Each result should have a 'matches' array now with `includeMatches`
expect(wrapper.state('results')[0].matches.length).to.not.equal(0);
Expand All @@ -132,14 +144,29 @@ describe('<FuzzySearch />', () => {
/>,
);

const input = wrapper.find('input');
input.simulate('change', {
target: {
value: 'f',
},
});
triggerDropdown(wrapper, 'f');

// Each result should have a 'matches' array now with `includeMatches`
expect(wrapper.state('results')[0].item.title).to.equal('The Great Gatsby');
});

it('should set input value even if no title on selectedValue (if ID set)', () => {
const wrapper = mount(
<FuzzySearch
list={list}
id={'title'}
keys={['author', 'title']}
onSelect={sinon.spy()}
shouldFillInputWithSelection
/>,
);

triggerDropdown(wrapper);

wrapper.find('.react-fuzzy-search').simulate('keydown', {
keyCode: 13,
});

expect(wrapper.find('input').props().value).to.equal('The Great Gatsby');
});
});

0 comments on commit a4ee1d0

Please sign in to comment.