Permalink
Browse files

Allow users to specify noResultsText

Currently if there are no search results the message displayed
is the same one used when a user hasn't started typing.

This change enables users of Async to provide different messaging when
a user has not started typing vs when no records matched a search.
  • Loading branch information...
DanielHeath committed Oct 9, 2016
1 parent c40fea0 commit 37613de11e2f6639254267e4ea36d21dabcce011
Showing with 91 additions and 3 deletions.
  1. +30 −3 src/Async.js
  2. +61 −0 test/Async-test.js
View
@@ -8,7 +8,7 @@ const propTypes = {
children: React.PropTypes.func.isRequired, // Child function responsible for creating the inner Select component; (props: Object): PropTypes.element
ignoreAccents: React.PropTypes.bool, // strip diacritics when filtering; defaults to true
ignoreCase: React.PropTypes.bool, // perform case-insensitive filtering; defaults to true
loadingPlaceholder: React.PropTypes.oneOfType([ // replaces the placeholder while options are loading
loadingPlaceholder: React.PropTypes.oneOfType([ // replaces the placeholder while options are loading
React.PropTypes.string,
React.PropTypes.node
]),
@@ -18,11 +18,16 @@ const propTypes = {
React.PropTypes.string,
React.PropTypes.node
]),
noResultsText: React.PropTypes.oneOfType([ // field noResultsText, displayed when no options come back from the server
React.PropTypes.string,
React.PropTypes.node
]),
searchPromptText: React.PropTypes.oneOfType([ // label to prompt for search input
React.PropTypes.string,
React.PropTypes.node
]),
onInputChange: React.PropTypes.func, // optional for keeping track of what is being typed
value: React.PropTypes.any, // initial field value
};
const defaultProps = {
@@ -139,12 +144,34 @@ export default class Async extends Component {
return this.loadOptions(inputValue);
}
inputValue() {
if (this.select) {
return this.select.state.inputValue;
}
return '';
}
noResultsText() {
const { loadingPlaceholder, noResultsText, searchPromptText } = this.props;
const { isLoading } = this.state;
const inputValue = this.inputValue();
if (isLoading) {
return loadingPlaceholder;
}
if (inputValue && noResultsText) {
return noResultsText;
}
return searchPromptText;
}
render () {
const { children, loadingPlaceholder, placeholder, searchPromptText } = this.props;
const { children, loadingPlaceholder, placeholder } = this.props;
const { isLoading, options } = this.state;
const props = {
noResultsText: isLoading ? loadingPlaceholder : searchPromptText,
noResultsText: this.noResultsText(),
placeholder: isLoading ? loadingPlaceholder : placeholder,
options: isLoading ? [] : options,
ref: (ref) => (this.select = ref)
View
@@ -333,6 +333,67 @@ describe('Async', () => {
});
});
describe('noResultsText', () => {
beforeEach(() => {
createControl({
searchPromptText: 'searchPromptText',
loadingPlaceholder: 'loadingPlaceholder',
noResultsText: 'noResultsText',
});
});
describe('before the user inputs text', () => {
it('returns the searchPromptText', () => {
expect(asyncInstance.noResultsText(), 'to equal', 'searchPromptText');
});
});
describe('while results are loading', () => {
beforeEach((cb) => {
asyncInstance.setState({
isLoading: true,
}, cb);
});
it('returns the loading indicator', () => {
asyncInstance.select = { state: { inputValue: 'asdf' } };
expect(asyncInstance.noResultsText(), 'to equal', 'loadingPlaceholder');
});
});
describe('after an empty result set loads', () => {
beforeEach((cb) => {
asyncInstance.setState({
isLoading: false,
}, cb);
});
describe('if noResultsText has been provided', () => {
it('returns the noResultsText', () => {
asyncInstance.select = { state: { inputValue: 'asdf' } };
expect(asyncInstance.noResultsText(), 'to equal', 'noResultsText');
});
});
describe('if noResultsText is empty', () => {
beforeEach((cb) => {
createControl({
searchPromptText: 'searchPromptText',
loadingPlaceholder: 'loadingPlaceholder'
});
asyncInstance.setState({
isLoading: false,
inputValue: 'asdfkljhadsf'
}, cb);
});
it('falls back to searchPromptText', () => {
asyncInstance.select = { state: { inputValue: 'asdf' } };
expect(asyncInstance.noResultsText(), 'to equal', 'searchPromptText');
});
});
});
});
describe('children function', () => {
it('should allow a custom select type to be rendered', () => {
let childProps;

0 comments on commit 37613de

Please sign in to comment.