Skip to content
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

feat(clearOnSelected): allow users to clear the input instead of filling #244

Merged
merged 5 commits into from
Aug 7, 2018

Conversation

Haroenv
Copy link
Contributor

@Haroenv Haroenv commented Aug 6, 2018

In some use-cases, like when you're using autocomplete to make tags on a page, or using the output in any other way than prefilling the query, you don't want the suggested value to show in the input, but would rather like it to be empty.

Before this PR it was basically impossible to have your input not filled, since it came back on blur and a few different places (see resetInputValue)

fixes #241

now there's a new option:

autocomplete('#input', { clearOnSelected: true }, /* ... */)

This makes sure the input clears after selecting, rather dan filling

In some use-cases, like when you're using autocomplete to make tags on a page, or using the output in any other way than prefilling the query, you don't want the suggested value to show in the input, but would rather like it to be empty.

Before this PR it was basically impossible to have your input not filled, since it came back on blur and a few different places (see `resetInputValue`

fixes #241
@Haroenv Haroenv requested a review from redox August 6, 2018 13:05
@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 6, 2018

@alystair, can you check this PR? you need to use the new option, but don't need to change the value in selected anymore

@coveralls
Copy link

coveralls commented Aug 6, 2018

Coverage Status

Coverage increased (+0.04%) to 88.842% when pulling 66db126 on feat/clearOnSelected into c194736 on master.

@alystair
Copy link

alystair commented Aug 6, 2018

Sorry being a bit of a novice here, I fetched your PR, then loaded the scripts:

<script src="//cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
<script src="/autocomplete.js/index.js"></script>

Resulting in the following:

index.js:3 Uncaught ReferenceError: module is not defined at index.js:3

Which leads to autocomplete is not defined in our own code. We don't use any frameworks.

@alystair
Copy link

alystair commented Aug 6, 2018

If I try loading standalone/index.js directly it does

Uncaught ReferenceError: require is not defined at index.js:4

@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 6, 2018

@alystair for now you'll only be able to try it by cloning the repository, then you do yarn && yarn build and copy the file out of /dist in place of your existing one

@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 6, 2018

@alystair
Copy link

alystair commented Aug 6, 2018

Doesn't seem to do anything, it reacts the same way as originally shown in issue.

Here's the code on my end:

let brands = client.initIndex('brands');
autocomplete('[name=sponsors]',
	{ clearOnSelected:true },{
		source: autocomplete.sources.hits(brands, {filters:'type:sponsor OR type:broadcasting'})
		,templates: {
			suggestion: function(suggestion) { return '<span>'+suggestion._highlightResult.name.value+'<img src="static/brands/'+suggestion['type'].charAt(0).toLowerCase()+'_'+suggestion.name.replace(/\s/g, '')+'.png'+'" alt=""></span>'; }
			,empty: function emptyTemplate() { return '<div class="aa-empty">Brand not in our database - consider <a href="mailto:XXXXXXX">suggesting it</a></div>'; }
		}
	}).on('autocomplete:selected', function(event, suggestion, dataset) {
		let exists = this.parentElement.parentElement.querySelector('[data-guid="'+suggestion['guid']+'"]');
		if (exists) { //existing tag
		// our tagging code
		} else { // create new tag
		// our tagging code
		}
	this.value = '';
	}).on('autocomplete:closed', function(event) {
		this.value='';
	});

@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 6, 2018

let brands = client.initIndex('brands');
autocomplete('[name=sponsors]',
	{ clearOnSelected:true },{
		source: autocomplete.sources.hits(brands, {filters:'type:sponsor OR type:broadcasting'})
		,templates: {
			suggestion: function(suggestion) { return '<span>'+suggestion._highlightResult.name.value+'<img src="static/brands/'+suggestion['type'].charAt(0).toLowerCase()+'_'+suggestion.name.replace(/\s/g, '')+'.png'+'" alt=""></span>'; }
			,empty: function emptyTemplate() { return '<div class="aa-empty">Brand not in our database - consider <a href="mailto:XXXXXXX">suggesting it</a></div>'; }
		}
	}).on('autocomplete:selected', function(event, suggestion, dataset) {
		let exists = this.parentElement.parentElement.querySelector('[data-guid="'+suggestion['guid']+'"]');
		if (exists) { //existing tag
		// our tagging code
		} else { // create new tag
		// our tagging code
		}
	})

@alystair
Copy link

alystair commented Aug 6, 2018

That doesn't change behavior on blur, as soon as it loses focus the input is restored.

I believe this is caused by this.resetInputValue(); in the _onBlur function (line 2417) - should add a check for your newly minted clearOnSelected option and we're in business. :)

@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 6, 2018

Hmm, this didn’t happen to me when testing, but I have an idea what the cause is :)

@@ -417,7 +418,11 @@ _.mixin(Typeahead.prototype, {
if (typeof datum.value !== 'undefined') {
this.input.setQuery(datum.value);
}
this.input.setInputValue(datum.value, true);
if (this.clearOnSelected) {
this.input.setInputValue('', true);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add setQuery here too

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add this.input.setQuery(''); here and we gucci 👍

@alystair
Copy link

alystair commented Aug 6, 2018

This made no difference, the only fix that worked for me was to comment out this.resetInputValue(); in the _onBlur function. Even though we're wiping input value (like I did by just adding this.value='' in the original suggest callback event) it resets it to the this.query value which is untouched.

@alystair
Copy link

alystair commented Aug 6, 2018

if you add this.input.setQuery(''); to your latest revision it works well.

@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 6, 2018

perfect, I had that initially but accidentally reversed it while developing the tests. It should work completely now @alystair

@alystair
Copy link

alystair commented Aug 6, 2018

Great, ship it 👍

@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 7, 2018

Demo of this behaviour in a codesandbox: https://codesandbox.io/s/j76mlmzq4v

(would really like a build being done in travis that can be hot linked :p )

Copy link
Contributor

@bobylito bobylito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few suggestions. Otherwise it seems solid 👍

view.input.trigger('enterKeyed', $e);

expect(spy).toHaveBeenCalled();
expect(view.input.setQuery).toHaveBeenCalledWith('');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check the value of this.$input rather than checking that some methods have been called (in order to not test how the code is done)?
Also would it be possible to have some value to check that there is an actual change of state (this would be a requirement if we can test without spy)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, but didn't know how to set a query here via code 🤔

view.$input.on('autocomplete:selected', spy);
view.input.trigger('enterKeyed', $e);

expect(spy).toHaveBeenCalled();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you test the values that the callback receives?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's already tested in other tests, this behaviour doesn't change that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why test that it has been called. This feature could mess with the parameters if we do not know the actual implementation.

@@ -31,6 +31,7 @@ function Typeahead(o) {
this.openOnFocus = !!o.openOnFocus;
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
this.autoWidth = (o.autoWidth === undefined) ? true : !!o.autoWidth;
this.clearOnSelected = !!o.clearOnSelected;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using Boolean(o.clearOnSelected) instead of !!o.clearOnSelected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is in the same style as the other options, technically both are the same :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are the same, indeed. Just not used to see that anymore. If it's consistent, good for me.

Copy link
Contributor

@bobylito bobylito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@Haroenv Haroenv merged commit aa2edbb into master Aug 7, 2018
@alystair
Copy link

alystair commented Aug 7, 2018

Is there an ETA of when this change will hit the CDNs? We'll use a local copy until then. Thanks again.

@samouss samouss deleted the feat/clearOnSelected branch August 7, 2018 15:31
@Haroenv
Copy link
Contributor Author

Haroenv commented Aug 7, 2018

@alystair I'll release tomorrow morning

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unfocusing input element reverts value to typed contents (urgent)
4 participants