-
Notifications
You must be signed in to change notification settings - Fork 149
Fix custom templates issue with defaultValue #425
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
base: main
Are you sure you want to change the base?
Changes from all commits
21b6550
3921fc4
fdc205e
8c424e1
8baad85
4b55ff3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,12 +60,15 @@ export default class Autocomplete extends Component { | |
constructor (props) { | ||
super(props) | ||
|
||
const { defaultValue } = props | ||
const isQueryAnOption = defaultValue.length > 0 ? this.isQueryAnOption(defaultValue, [defaultValue]) : false | ||
|
||
this.state = { | ||
focused: null, | ||
hovered: null, | ||
menuOpen: false, | ||
options: props.defaultValue ? [props.defaultValue] : [], | ||
query: props.defaultValue, | ||
options: isQueryAnOption ? [defaultValue] : [], | ||
query: defaultValue, | ||
validChoiceMade: false, | ||
selected: null, | ||
ariaHint: true | ||
|
@@ -95,7 +98,7 @@ export default class Autocomplete extends Component { | |
} | ||
|
||
isQueryAnOption (query, options) { | ||
return options.map(entry => this.templateInputValue(entry).toLowerCase()).indexOf(query.toLowerCase()) !== -1 | ||
return options.some(entry => (this.templateInputValue(entry) || '').toLowerCase() === query.toLowerCase()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just want to check that I'm reading this correctly – this function is effectively doing the same thing as before, it's just using slightly neater syntax and allowing for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, except that:
is more broadly " templates: {
inputValue: function(suggestion) {
return suggestion && suggestion.Title;
}
} which you have to do if you're providing an |
||
} | ||
|
||
componentDidMount () { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -327,6 +327,39 @@ describe('Autocomplete', () => { | |
expect(autocomplete.state.options[0]).to.equal('France') | ||
expect(autocomplete.state.query).to.equal('France') | ||
}) | ||
|
||
it('is prefilled with a simple custom inputValue template', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to write these tests that makes it more explicit what's going on? They currently feel like they're relying on a side effect of the way the |
||
autocomplete = new Autocomplete({ | ||
...Autocomplete.defaultProps, | ||
defaultValue: 'France', | ||
id: 'test', | ||
source: suggest, | ||
templates: { | ||
inputValue: suggestion => suggestion, | ||
suggestion: suggestion => `<a href="/search?q=${suggestion}">${suggestion}</a>` | ||
} | ||
}) | ||
|
||
expect(autocomplete.state.options.length).to.equal(1) | ||
expect(autocomplete.state.options[0]).to.equal('France') | ||
expect(autocomplete.state.query).to.equal('France') | ||
}) | ||
|
||
it('isn\'t prefilled with a custom inputValue template that returns a non-match', () => { | ||
autocomplete = new Autocomplete({ | ||
...Autocomplete.defaultProps, | ||
defaultValue: 'France', | ||
id: 'test', | ||
source: suggest, | ||
templates: { | ||
inputValue: suggestion => suggestion && suggestion.title, | ||
suggestion: suggestion => suggestion && `<a href="${suggestion.href}">${suggestion.title}</a>` | ||
} | ||
}) | ||
|
||
expect(autocomplete.state.options.length).to.equal(0) | ||
expect(autocomplete.state.query).to.equal('France') | ||
}) | ||
}) | ||
}) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem quite right to me, because we're passing a known value and an array containing exactly that known value to a function that's meant to test whether the value is in the array. What we really seem to be testing here is whether
this.templateInputValue
returns a value that matches or not, so should we just be calling that directly?I'm not sure
isQueryAnOption
really describes what's actually going on here either. Is there a better way to describe this?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are, but we want to use the value returned from
templateInputValue
as you rightly point:Fair point, the condition would then become something like this, which is definitely much simpler:
I think I was trying to re-use the existing
isQueryAnOption
function as it was already doing what we want.I guess the behaviour here is whether we should show the default value as an option on focus. So maybe,
showDefaultValueAsOption
or something? The state initialisation would then become:which seems to make sense!