From aa2edbb3297c7831468e188b3933f593f4e7be3b Mon Sep 17 00:00:00 2001 From: Haroen Viaene Date: Tue, 7 Aug 2018 17:09:33 +0200 Subject: [PATCH] feat(clearOnSelected): allow users to clear the input instead of filling (#244) * feat(clearOnSelected): allow users to clear the input instead of 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 * fix: make sure both query and input are '' * chore: update test * chore: test implem of callback too * chore: more specific test --- README.md | 2 ++ examples/basic.html | 2 +- src/angular/directive.js | 1 + src/autocomplete/typeahead.js | 7 ++++++- src/jquery/plugin.js | 1 + src/standalone/index.js | 1 + test/unit/typeahead_spec.js | 32 +++++++++++++++++++++++++++++++- 7 files changed, 43 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index df9bae297..cea0852b8 100644 --- a/README.md +++ b/README.md @@ -290,6 +290,8 @@ When initializing an autocomplete, there are a number of options you can configu * `debug` – If `true`, the autocomplete will not close on `blur`. Defaults to `false`. +* `clearOnSelected` – If `true`, the autocomplete will empty the search box when a suggestion is selected. This is useful if you want to use this as a way to input tags using the `selected` event. + * `openOnFocus` – If `true`, the dropdown menu will open when the input is focused. Defaults to `false`. * `appendTo` – If set with a DOM selector, doesn't wrap the input and appends the wrapper and dropdown menu to the first DOM element matching the selector. It automatically positions the wrapper under the input, and sets it to the same width as the input. Can't be used with `hint: true`, because `hint` requires the wrapper around the input. diff --git a/examples/basic.html b/examples/basic.html index 8f1f6577a..66182d5db 100644 --- a/examples/basic.html +++ b/examples/basic.html @@ -51,7 +51,7 @@

Basic example

autocomplete('#search-input', { hint: false }, [ { source: autocomplete.sources.hits(index, { hitsPerPage: 5 }), - displayKey: 'my_attribute', + displayKey: 'name', templates: { suggestion: function(suggestion) { return suggestion._highlightResult.name.value; diff --git a/src/angular/directive.js b/src/angular/directive.js index 83ab0ff33..862b09df6 100644 --- a/src/angular/directive.js +++ b/src/angular/directive.js @@ -75,6 +75,7 @@ angular.module('algolia.autocomplete', []) openOnFocus: scope.options.openOnFocus, templates: scope.options.templates, debug: scope.options.debug, + clearOnSelected: scope.options.clearOnSelected, cssClasses: scope.options.cssClasses, datasets: scope.datasets, keyboardShortcuts: scope.options.keyboardShortcuts, diff --git a/src/autocomplete/typeahead.js b/src/autocomplete/typeahead.js index 441ef5209..2cec1b7b4 100644 --- a/src/autocomplete/typeahead.js +++ b/src/autocomplete/typeahead.js @@ -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; o.hint = !!o.hint; @@ -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.setVal(''); + } else { + this.input.setInputValue(datum.value, true); + } this._setLanguageDirection(); diff --git a/src/jquery/plugin.js b/src/jquery/plugin.js index c9b99cfdf..a633ed53a 100644 --- a/src/jquery/plugin.js +++ b/src/jquery/plugin.js @@ -60,6 +60,7 @@ methods = { openOnFocus: o.openOnFocus, templates: o.templates, debug: o.debug, + clearOnSelected: o.clearOnSelected, cssClasses: o.cssClasses, datasets: datasets, keyboardShortcuts: o.keyboardShortcuts, diff --git a/src/standalone/index.js b/src/standalone/index.js index 72406c24c..100daebaf 100644 --- a/src/standalone/index.js +++ b/src/standalone/index.js @@ -45,6 +45,7 @@ function autocomplete(selector, options, datasets, typeaheadObject) { openOnFocus: options.openOnFocus, templates: options.templates, debug: options.debug, + clearOnSelected: options.clearOnSelected, cssClasses: options.cssClasses, datasets: datasets, keyboardShortcuts: options.keyboardShortcuts, diff --git a/test/unit/typeahead_spec.js b/test/unit/typeahead_spec.js index 6a840b8e9..8888c969e 100644 --- a/test/unit/typeahead_spec.js +++ b/test/unit/typeahead_spec.js @@ -342,7 +342,6 @@ describe('Typeahead', function() { }); describe('when debug flag is set', function() { - beforeEach(function() { this.view = new Typeahead({ input: this.$input, @@ -368,6 +367,37 @@ describe('Typeahead', function() { }); }); + describe('when clearOnSelected flag is set to true', function() { + it('clears input when selected', function() { + var spy = jasmine.createSpy(); + var view = new Typeahead({ + input: this.$input, + clearOnSelected: true, + hint: true, + datasets: {} + }); + view.dropdown.getDatumForCursor.and.returnValue(testDatum); + + // select something, and clear + var $e = jasmine.createSpyObj('event', ['preventDefault']); + view.$input.on('autocomplete:selected', spy); + view.input.trigger('enterKeyed', $e); + + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(jasmine.objectContaining({ + type: 'autocomplete:selected', + target: jasmine.any(Object), + delegateTarget: jasmine.any(Object), + currentTarget: jasmine.any(Object), + handleObj: jasmine.objectContaining({ + type: 'autocomplete:selected' + }) + }), undefined, undefined); + expect(view.input.setQuery).toHaveBeenCalledWith(''); + expect(view.input.setInputValue).toHaveBeenCalledWith('', true); + }); + }); + describe('when input triggers enterKeyed', function() { beforeEach(function() { this.dropdown.getDatumForCursor.and.returnValue(testDatum);