From b43590c64f1a3e0f56d992059f12fe8befff27b7 Mon Sep 17 00:00:00 2001 From: Andrey Khomenko Date: Thu, 28 Jun 2018 02:11:08 -0400 Subject: [PATCH 1/4] fix(ac) don't use innerText --- .../components/paper-autocomplete-trigger.js | 8 +- addon/components/paper-autocomplete.js | 24 ++- addon/components/paper-chips.js | 54 +++---- addon/templates/components/paper-chips.hbs | 1 + .../dummy/app/templates/demo/autocomplete.hbs | 141 ++++-------------- yarn.lock | 6 +- 6 files changed, 81 insertions(+), 153 deletions(-) diff --git a/addon/components/paper-autocomplete-trigger.js b/addon/components/paper-autocomplete-trigger.js index 0bdbfc770..9ba5fe334 100644 --- a/addon/components/paper-autocomplete-trigger.js +++ b/addon/components/paper-autocomplete-trigger.js @@ -19,7 +19,6 @@ export default Component.extend({ classNameBindings: ['noLabel:md-whiteframe-z1', 'select.isOpen:md-menu-showing', 'showingClearButton:md-show-clear-button'], noLabel: not('extra.label'), - _innerText: oneWay('searchText'), showingClearButton: computed('allowClear', 'disabled', 'resetButtonDestroyed', function() { // make room for clear button: @@ -30,23 +29,20 @@ export default Component.extend({ ); }), - text: computed('select', 'searchText', '_innerText', { + text: computed('select', 'searchText', { get() { let { select, searchText, - _innerText } = this.getProperties('select', 'searchText', '_innerText'); if (select && select.selected) { return this.getSelectedAsText(); } - return searchText ? searchText : _innerText; + return searchText; }, set(_, v) { let { select, searchText } = this.getProperties('select', 'searchText'); - this.set('_innerText', v); - // searchText should always win if (!(select && select.selected) && isPresent(searchText)) { return searchText; diff --git a/addon/components/paper-autocomplete.js b/addon/components/paper-autocomplete.js index 03fdf4319..48f9b3f0b 100644 --- a/addon/components/paper-autocomplete.js +++ b/addon/components/paper-autocomplete.js @@ -5,8 +5,8 @@ import { inject as service } from '@ember/service'; import { alias } from '@ember/object/computed'; import { assert } from '@ember/debug'; -import { isNone } from '@ember/utils'; -import { defineProperty, computed } from '@ember/object'; +import { isNone, isPresent } from '@ember/utils'; +import { defineProperty, aliasMethod, computed } from '@ember/object'; import PowerSelect from 'ember-power-select/components/power-select'; import layout from '../templates/components/paper-autocomplete'; import ValidationMixin from 'ember-paper/mixins/validation-mixin'; @@ -56,6 +56,10 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { return classes.join(' '); }), + _onSearchTextChange(value) { + this.set('searchText', value); + }, + init() { this._initComponent(); this._super(...arguments); @@ -63,6 +67,7 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { // Init autocomplete component _initComponent() { + // eslint-disable-line let { onSearchTextChange, onSelectionChange @@ -74,7 +79,11 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { assert('{{paper-autocomplete}} requires at least one of the `onSelectionChange` or `onSearchTextChange` functions to be provided.', hasTextChange || hasSelectionChange); let aliasOnChangeDepKey = hasSelectionChange ? 'onSelectionChange' : '_onChangeNop'; - defineProperty(this, 'oninput', alias('onSearchTextChange')); + this.oninput = (function() { + let handler = this.get('onSearchTextChange') || this.get('_onSearchTextChange'); + handler.call(this, ...arguments); + }).bind(this); + defineProperty(this, 'onchange', alias(aliasOnChangeDepKey)); }, @@ -88,6 +97,15 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { this._super(...arguments); }, + didReceiveAttrs() { + let { searchText, _prevSearchText } = this.getProperties('searchText', '_prevSearchText'); + if (!isPresent(searchText) && isPresent(_prevSearchText)) { + this._resetSearch(); + } + this.set('_prevSearchText', searchText); + this._super(...arguments); + }, + actions: { onTriggerMouseDown() { diff --git a/addon/components/paper-chips.js b/addon/components/paper-chips.js index a21c4fdbe..4a6541cab 100644 --- a/addon/components/paper-chips.js +++ b/addon/components/paper-chips.js @@ -142,22 +142,22 @@ export default Component.extend({ if (item) { // Trigger onChange for the new item. this.sendAction('addItem', item); - - this.queueReset(); + this.set('searchText', ''); + // this.queueReset(); // Track selection of last item if no match required. if (this.get('options').length === 1 && !this.get('requireMatch')) { this.set('lastItemChosen', true); this.set('autocomplete', null); } - - return true; } }, - searchTextChange(searchText, select) { + searchTextChange(value, select) { + this.set('searchText', value); + // Close dropdown if search text is cleared by the user. - if (isEmpty(searchText)) { + if (isEmpty(value)) { select.actions.close(); } }, @@ -222,31 +222,31 @@ export default Component.extend({ }, resetInput() { - let select = this.get('autocomplete'); - let input = this.getInput(); - - if (input.is('.ember-paper-autocomplete-search-input') && isPresent(select)) { - // Reset the underlying ember-power-select so that it's ready for another selection. - input.val(''); - select.actions.search(''); - - // Close the dropdown after focusing the field. - input.focus(); - select.actions.close(); - } else { - input.focus(); - } - - this.set('focusedElement', 'input'); - this.set('resetTimer', null); + // let select = this.get('autocomplete'); + // let input = this.getInput(); + + // if (input.is('.ember-paper-autocomplete-search-input') && isPresent(select)) { + // // Reset the underlying ember-power-select so that it's ready for another selection. + // input.val(''); + // select.actions.search(''); + + // // Close the dropdown after focusing the field. + // input.focus(); + // select.actions.close(); + // } else { + // input.focus(); + // } + + // this.set('focusedElement', 'input'); + // this.set('resetTimer', null); }, queueReset() { - if (this.get('resetTimer')) { - run.cancel(this.get('resetTimer')); - } + // if (this.get('resetTimer')) { + // run.cancel(this.get('resetTimer')); + // } - this.set('resetTimer', run.next(this, this.resetInput)); + // this.set('resetTimer', run.next(this, this.resetInput)); }, closeAutocomplete() { diff --git a/addon/templates/components/paper-chips.hbs b/addon/templates/components/paper-chips.hbs index 9a029e42c..6883473cb 100644 --- a/addon/templates/components/paper-chips.hbs +++ b/addon/templates/components/paper-chips.hbs @@ -37,6 +37,7 @@ search=search matcher=matcher noMatchesMessage=noMatchesMessage + searchText=(readonly searchText) onBlur=(action "inputBlur") onSelectionChange=(action "autocompleteChange") onSearchTextChange=(action "searchTextChange") diff --git a/tests/dummy/app/templates/demo/autocomplete.hbs b/tests/dummy/app/templates/demo/autocomplete.hbs index 6a4c184b4..1937db193 100644 --- a/tests/dummy/app/templates/demo/autocomplete.hbs +++ b/tests/dummy/app/templates/demo/autocomplete.hbs @@ -4,7 +4,7 @@ {{#paper-card}} {{#paper-card-content}} -

Basic Usage

+

Two way binding: Basic Usage {{countrySearchText}}

Use \{{paper-autocomplete}} to search for matches from local or remote data sources.
{{! BEGIN-SNIPPET autocomplete.basic-usage }} @@ -13,8 +13,7 @@ onCreate=(action "addCountry") options=items allowClear=true - searchText=(readonly countrySearchText) - onSearchTextChange=(action (mut countrySearchText)) + searchText=countrySearchText selected=selectedCountry search=(if simulateQuery (action "searchCountries")) searchField="name" @@ -29,126 +28,40 @@ flags="i"}} {{/paper-autocomplete}} {{! END-SNIPPET }} + {{/paper-card-content}} +{{paper-button primary=true label="Clear" onClick=(action (mut countrySearchText) "")}} -

- {{#if selectedCountry}} - Selected country is {{selectedCountry.name}} ({{selectedCountry.code}}) - {{else}} - Nothing selected... - {{/if}} -

- {{#paper-checkbox - value=firstDisabled - onChange=(action (mut firstDisabled))}} - Disable input - {{/paper-checkbox}} - {{#paper-checkbox - value=simulateQuery - onChange=(action (mut simulateQuery))}} - Simulate query - {{/paper-checkbox}} +{{/paper-card}} -

Template

- {{code-snippet name="autocomplete.basic-usage.hbs"}} - {{/paper-card-content}} - {{/paper-card}} - {{#paper-card}} +{{#paper-card}} {{#paper-card-content}} -

Block Custom template

-
Use \{{paper-autocomplete}} with custom templates to show styled autocomplete results.
- - {{!-- searchText=(readonly templateSeachText) --}} +

With action: {{countrySearchText2}}

- {{! BEGIN-SNIPPET autocomplete.block-custom-template }} + {{! BEGIN-SNIPPET autocomplete.basic-usage }} {{#paper-autocomplete - placeholder="Type e.g. ember, paper, one, two etc." - options=arrayOfItems - selected=selectedItem - onSelectionChange=(action (mut selectedItem)) - as |item term|}} - - {{paper-icon "star"}} - - {{paper-autocomplete-highlight searchText=term.searchText flags="i" label=item}} - - - {{else}} - Whoops! could not find! + disabled=firstDisabled + options=items + allowClear=true + searchText=(readonly countrySearchText2) + onSearchTextChange=(action (mut countrySearchText2)) + selected=selectedCountry2 + searchField="name" + labelPath="name" + placeholder="Select a Country..." + loadingMessage="Searching countries..." + noMatchesMessage="Oops this country doesn't exist. Create a new country?" + onSelectionChange=(action (mut selectedCountry2)) as |country autocomplete|}} + {{paper-autocomplete-highlight + label=country.name + searchText=autocomplete.searchText + flags="i"}} {{/paper-autocomplete}} {{! END-SNIPPET }} + {{/paper-card-content}} +{{paper-button primary=true label="Clear" onClick=(action (mut countrySearchText2) "")}} -

- Selected: {{if selectedItem selectedItem "None"}} -

- -

Template

- {{code-snippet name="autocomplete.block-custom-template.hbs"}} - {{/paper-card-content}} - {{/paper-card}} - - {{#paper-card}} - {{#paper-card-content}} -

Floating Label

-
The following example demonstrates floating labels being used as a normal form element.
-
- {{! BEGIN-SNIPPET autocomplete.floating-label }} - {{paper-input label="Name" value=name onChange=(action (mut name)) class="flex"}} - {{#paper-autocomplete - disabled=(readonly disabled2) - required=(readonly isRequired) - triggerClass="flex" - options=items - selected=selectedCountry2 - search=(if simulateQuery2 (action "searchCountries")) - searchField="name" - labelPath="name" - label="Select a Country..." - allowClear=(readonly allowClearWithLabel) - loadingMessage="Searching countries..." - noMatchesMessage="Oops this country doesn't exist." - onSelectionChange=(action (mut selectedCountry2)) as |country select|}} - {{paper-autocomplete-highlight - label=country.name - searchText=select.searchText - flags="i"}} - {{/paper-autocomplete}} - - {{! END-SNIPPET }} -
-

- {{#if selectedCountry2}} - Selected country is {{selectedCountry2.name}} ({{selectedCountry2.code}}) - {{else}} - Nothing is selected. - {{/if}} -

- {{#paper-checkbox - value=(readonly disabled2) - onChange=(action (mut disabled2))}} - Disable input - {{/paper-checkbox}} - {{#paper-checkbox - value=(readonly simulateQuery2) - onChange=(action (mut simulateQuery2))}} - Simulate query - {{/paper-checkbox}} - {{#paper-checkbox - value=isRequired - onChange=(action (mut isRequired))}} - Is required - {{/paper-checkbox}} - {{#paper-checkbox - value=(readonly allowClearWithLabel) - onChange=(action (mut allowClearWithLabel))}} - Allow Clear - {{/paper-checkbox}} - -

Template

- {{code-snippet name="autocomplete.floating-label.hbs"}} - - {{/paper-card-content}} - {{/paper-card}} +{{/paper-card}} {{/doc-content}} diff --git a/yarn.lock b/yarn.lock index a798bd47d..711b990fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2734,9 +2734,9 @@ ember-cp-validations@^4.0.0-beta.0: ember-require-module "^0.2.0" ember-validators "^1.1.1" -ember-css-transitions@^0.1.14: - version "0.1.14" - resolved "https://registry.yarnpkg.com/ember-css-transitions/-/ember-css-transitions-0.1.14.tgz#85cbaad976bd8b5b4d88f2b4d517c00dc97455e4" +ember-css-transitions@^0.1.15: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ember-css-transitions/-/ember-css-transitions-0.1.15.tgz#2a5b5fbba72092444edfe7fec315bb685250491d" dependencies: ember-cli-babel "^6.6.0" From 41a370ab5995455065208e1c3e5910eebfb33da6 Mon Sep 17 00:00:00 2001 From: Paul Nicholls Date: Fri, 29 Jun 2018 09:43:49 +1200 Subject: [PATCH 2/4] Chips: Remove all custom input resetting logic Custom input resetting logic is no longer required, thanks to improvements to paper-autocomplete. --- addon/components/paper-chips.js | 40 +-------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/addon/components/paper-chips.js b/addon/components/paper-chips.js index 4a6541cab..a8cd48703 100644 --- a/addon/components/paper-chips.js +++ b/addon/components/paper-chips.js @@ -1,7 +1,6 @@ import Component from '@ember/component'; import { isPresent, isEmpty } from '@ember/utils'; import { observer, computed } from '@ember/object'; -import { run } from '@ember/runloop'; import layout from '../templates/components/paper-chips'; export default Component.extend({ @@ -17,7 +16,6 @@ export default Component.extend({ return true; }), - resetTimer: null, lastItemChosen: false, handleFocusChange: observer('focusedElement', 'activeChip', function() { @@ -55,11 +53,7 @@ export default Component.extend({ this.sendAction('addItem', item); this.set('newChipValue', ''); - - if (isPresent(this.get('autocomplete'))) { - // We have an autocomplete - reset it once it's closed itself. - this.queueReset(); - } + this.set('searchText', ''); } }, @@ -68,7 +62,6 @@ export default Component.extend({ let current = this.get('activeChip'); if (current === -1 || current >= this.get('content').length) { - this.queueReset(); this.set('activeChip', -1); } }, @@ -143,7 +136,6 @@ export default Component.extend({ // Trigger onChange for the new item. this.sendAction('addItem', item); this.set('searchText', ''); - // this.queueReset(); // Track selection of last item if no match required. if (this.get('options').length === 1 && !this.get('requireMatch')) { @@ -185,7 +177,6 @@ export default Component.extend({ event.stopPropagation(); return false; } - } }, @@ -215,40 +206,11 @@ export default Component.extend({ } else if (current >= 0 && ['Backspace', 'Delete', 'Del'].includes(key)) { this.sendAction('removeItem', chips[current]); if (current >= chips.length) { - this.queueReset(); this.set('activeChip', -1); } } }, - resetInput() { - // let select = this.get('autocomplete'); - // let input = this.getInput(); - - // if (input.is('.ember-paper-autocomplete-search-input') && isPresent(select)) { - // // Reset the underlying ember-power-select so that it's ready for another selection. - // input.val(''); - // select.actions.search(''); - - // // Close the dropdown after focusing the field. - // input.focus(); - // select.actions.close(); - // } else { - // input.focus(); - // } - - // this.set('focusedElement', 'input'); - // this.set('resetTimer', null); - }, - - queueReset() { - // if (this.get('resetTimer')) { - // run.cancel(this.get('resetTimer')); - // } - - // this.set('resetTimer', run.next(this, this.resetInput)); - }, - closeAutocomplete() { if (!isEmpty(this.get('autocomplete')) && !isEmpty(this.get('autocomplete').actions)) { this.get('autocomplete').actions.close(); From e4917f884f10d8164c10f6debc0550e550a10b9c Mon Sep 17 00:00:00 2001 From: Andrey Khomenko Date: Tue, 10 Jul 2018 01:08:38 -0400 Subject: [PATCH 3/4] fix(ac): use select.searchText instead of innerText --- .../components/paper-autocomplete-trigger.js | 42 +---- addon/components/paper-autocomplete.js | 27 ++-- .../components/paper-autocomplete-trigger.hbs | 3 +- .../components/paper-autocomplete.hbs | 1 - .../dummy/app/templates/demo/autocomplete.hbs | 149 ++++++++++++++---- 5 files changed, 144 insertions(+), 78 deletions(-) diff --git a/addon/components/paper-autocomplete-trigger.js b/addon/components/paper-autocomplete-trigger.js index 9ba5fe334..e7a8f7e98 100644 --- a/addon/components/paper-autocomplete-trigger.js +++ b/addon/components/paper-autocomplete-trigger.js @@ -1,10 +1,9 @@ /** * @module ember-paper */ -import { not, oneWay } from '@ember/object/computed'; - import Component from '@ember/component'; -import { isBlank, isPresent } from '@ember/utils'; +import { not } from '@ember/object/computed'; +import { isBlank } from '@ember/utils'; import { run } from '@ember/runloop'; import { computed, get } from '@ember/object'; import layout from '../templates/components/paper-autocomplete-trigger'; @@ -19,7 +18,6 @@ export default Component.extend({ classNameBindings: ['noLabel:md-whiteframe-z1', 'select.isOpen:md-menu-showing', 'showingClearButton:md-show-clear-button'], noLabel: not('extra.label'), - showingClearButton: computed('allowClear', 'disabled', 'resetButtonDestroyed', function() { // make room for clear button: // - if we're enabled @@ -29,28 +27,13 @@ export default Component.extend({ ); }), - text: computed('select', 'searchText', { - get() { - let { - select, - searchText, - } = this.getProperties('select', 'searchText', '_innerText'); - - if (select && select.selected) { - return this.getSelectedAsText(); - } - return searchText; - }, - set(_, v) { - let { select, searchText } = this.getProperties('select', 'searchText'); - // searchText should always win - if (!(select && select.selected) && isPresent(searchText)) { - return searchText; - } - - return v; + text: computed('select.{searchText,selected}', function() { + let selected = this.get('select.selected'); + if (selected) { + return this.getSelectedAsText(); } - }), + return this.get('select.searchText'); + }).readOnly(), // Lifecycle hooks didUpdateAttrs() { @@ -60,21 +43,15 @@ export default Component.extend({ * the select box. But we also close the select box when we're loading search results and when * we remove input text -- so protect against this */ - let oldSelect = this.get('_oldSelect'); let oldLastSearchedText = this.get('_lastSearchedText'); let oldLoading = this.get('_loading'); let oldDisabled = this.get('_lastDisabled'); let select = this.get('select'); let loading = this.get('loading'); - let searchText = this.get('searchText'); let lastSearchedText = this.get('lastSearchedText'); let disabled = this.get('disabled'); - if (oldSelect && oldSelect.isOpen && !select.isOpen && !loading && searchText) { - this.set('text', this.getSelectedAsText()); - } - if (lastSearchedText !== oldLastSearchedText) { if (isBlank(lastSearchedText)) { run.schedule('actions', null, select.actions.close, null, true); @@ -92,7 +69,6 @@ export default Component.extend({ } this.setProperties({ - _oldSelect: select, _lastSearchedText: lastSearchedText, _loading: loading, _lastDisabled: disabled @@ -107,7 +83,6 @@ export default Component.extend({ clear(e) { e.stopPropagation(); - this.set('text', ''); if (this.get('onClear')) { this.get('onClear')(); } else { @@ -132,7 +107,6 @@ export default Component.extend({ this.get('select').actions.select(null); } this.get('onInput')(e.target ? e : { target: { value: e } }); - this.set('text', e.target ? e.target.value : e); }, resetButtonDestroyed() { diff --git a/addon/components/paper-autocomplete.js b/addon/components/paper-autocomplete.js index 48f9b3f0b..a92e3f2b7 100644 --- a/addon/components/paper-autocomplete.js +++ b/addon/components/paper-autocomplete.js @@ -5,8 +5,8 @@ import { inject as service } from '@ember/service'; import { alias } from '@ember/object/computed'; import { assert } from '@ember/debug'; -import { isNone, isPresent } from '@ember/utils'; -import { defineProperty, aliasMethod, computed } from '@ember/object'; +import { isNone } from '@ember/utils'; +import { defineProperty, computed } from '@ember/object'; import PowerSelect from 'ember-power-select/components/power-select'; import layout from '../templates/components/paper-autocomplete'; import ValidationMixin from 'ember-paper/mixins/validation-mixin'; @@ -56,8 +56,10 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { return classes.join(' '); }), - _onSearchTextChange(value) { - this.set('searchText', value); + _onInput(value) { + let handler = this.get('onSearchTextChange') || ((v) => this.set('searchText', v)); + handler(...arguments); + return value; }, init() { @@ -67,7 +69,6 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { // Init autocomplete component _initComponent() { - // eslint-disable-line let { onSearchTextChange, onSelectionChange @@ -79,12 +80,8 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { assert('{{paper-autocomplete}} requires at least one of the `onSelectionChange` or `onSearchTextChange` functions to be provided.', hasTextChange || hasSelectionChange); let aliasOnChangeDepKey = hasSelectionChange ? 'onSelectionChange' : '_onChangeNop'; - this.oninput = (function() { - let handler = this.get('onSearchTextChange') || this.get('_onSearchTextChange'); - handler.call(this, ...arguments); - }).bind(this); - defineProperty(this, 'onchange', alias(aliasOnChangeDepKey)); + this.oninput = this._onInput.bind(this); }, // Choose highlighted item on key tab @@ -98,11 +95,13 @@ export default PowerSelect.extend(ValidationMixin, ChildMixin, { }, didReceiveAttrs() { - let { searchText, _prevSearchText } = this.getProperties('searchText', '_prevSearchText'); - if (!isPresent(searchText) && isPresent(_prevSearchText)) { - this._resetSearch(); + let searchText = this.get('searchText'); + if (searchText !== this.get('publicAPI.searchText')) { + let publicAPI = this.get('publicAPI'); + if (publicAPI && publicAPI.actions) { + publicAPI.actions.search(searchText); + } } - this.set('_prevSearchText', searchText); this._super(...arguments); }, diff --git a/addon/templates/components/paper-autocomplete-trigger.hbs b/addon/templates/components/paper-autocomplete-trigger.hbs index 073d690c5..9b520e806 100644 --- a/addon/templates/components/paper-autocomplete-trigger.hbs +++ b/addon/templates/components/paper-autocomplete-trigger.hbs @@ -16,11 +16,10 @@ hideAllMessages=hideAllMessages}} {{else}} Two way binding: Basic Usage {{countrySearchText}} +

Basic Usage

Use \{{paper-autocomplete}} to search for matches from local or remote data sources.
{{! BEGIN-SNIPPET autocomplete.basic-usage }} @@ -13,7 +13,8 @@ onCreate=(action "addCountry") options=items allowClear=true - searchText=countrySearchText + searchText=(readonly countrySearchText) + onSearchTextChange=(action (mut countrySearchText)) selected=selectedCountry search=(if simulateQuery (action "searchCountries")) searchField="name" @@ -28,40 +29,134 @@ flags="i"}} {{/paper-autocomplete}} {{! END-SNIPPET }} - {{/paper-card-content}} -{{paper-button primary=true label="Clear" onClick=(action (mut countrySearchText) "")}} -{{/paper-card}} +

+ {{#if selectedCountry}} + Selected country is {{selectedCountry.name}} ({{selectedCountry.code}}) + {{else}} + Nothing selected... + {{/if}} +

+ {{#paper-checkbox + value=firstDisabled + onChange=(action (mut firstDisabled))}} + Disable input + {{/paper-checkbox}} + {{#paper-checkbox + value=simulateQuery + onChange=(action (mut simulateQuery))}} + Simulate query + {{/paper-checkbox}} + {{paper-button + primary=true + label="Reset search-Text" + onClick=(action (mut countrySearchText) '')}} + {{paper-button + primary=true + label="Reset selected" + onClick=(action (mut selectedCountry) null)}} +

Template

+ {{code-snippet name="autocomplete.basic-usage.hbs"}} + {{/paper-card-content}} + {{/paper-card}} -{{#paper-card}} + {{#paper-card}} {{#paper-card-content}} -

With action: {{countrySearchText2}}

+

Block Custom template

+
Use \{{paper-autocomplete}} with custom templates to show styled autocomplete results.
- {{! BEGIN-SNIPPET autocomplete.basic-usage }} + {{!-- searchText=(readonly templateSeachText) --}} + + {{! BEGIN-SNIPPET autocomplete.block-custom-template }} {{#paper-autocomplete - disabled=firstDisabled - options=items - allowClear=true - searchText=(readonly countrySearchText2) - onSearchTextChange=(action (mut countrySearchText2)) - selected=selectedCountry2 - searchField="name" - labelPath="name" - placeholder="Select a Country..." - loadingMessage="Searching countries..." - noMatchesMessage="Oops this country doesn't exist. Create a new country?" - onSelectionChange=(action (mut selectedCountry2)) as |country autocomplete|}} - {{paper-autocomplete-highlight - label=country.name - searchText=autocomplete.searchText - flags="i"}} + placeholder="Type e.g. ember, paper, one, two etc." + options=arrayOfItems + selected=selectedItem + onSelectionChange=(action (mut selectedItem)) + as |item term|}} + + {{paper-icon "star"}} + + {{paper-autocomplete-highlight searchText=term.searchText flags="i" label=item}} + + + {{else}} + Whoops! could not find! {{/paper-autocomplete}} {{! END-SNIPPET }} - {{/paper-card-content}} -{{paper-button primary=true label="Clear" onClick=(action (mut countrySearchText2) "")}} -{{/paper-card}} +

+ Selected: {{if selectedItem selectedItem "None"}} +

+ +

Template

+ {{code-snippet name="autocomplete.block-custom-template.hbs"}} + {{/paper-card-content}} + {{/paper-card}} + + {{#paper-card}} + {{#paper-card-content}} +

Floating Label

+
The following example demonstrates floating labels being used as a normal form element.
+
+ {{! BEGIN-SNIPPET autocomplete.floating-label }} + {{paper-input label="Name" value=name onChange=(action (mut name)) class="flex"}} + {{#paper-autocomplete + disabled=(readonly disabled2) + required=(readonly isRequired) + triggerClass="flex" + options=items + selected=selectedCountry2 + search=(if simulateQuery2 (action "searchCountries")) + searchField="name" + labelPath="name" + label="Select a Country..." + allowClear=(readonly allowClearWithLabel) + loadingMessage="Searching countries..." + noMatchesMessage="Oops this country doesn't exist." + onSelectionChange=(action (mut selectedCountry2)) as |country select|}} + {{paper-autocomplete-highlight + label=country.name + searchText=select.searchText + flags="i"}} + {{/paper-autocomplete}} + + {{! END-SNIPPET }} +
+

+ {{#if selectedCountry2}} + Selected country is {{selectedCountry2.name}} ({{selectedCountry2.code}}) + {{else}} + Nothing is selected. + {{/if}} +

+ {{#paper-checkbox + value=(readonly disabled2) + onChange=(action (mut disabled2))}} + Disable input + {{/paper-checkbox}} + {{#paper-checkbox + value=(readonly simulateQuery2) + onChange=(action (mut simulateQuery2))}} + Simulate query + {{/paper-checkbox}} + {{#paper-checkbox + value=isRequired + onChange=(action (mut isRequired))}} + Is required + {{/paper-checkbox}} + {{#paper-checkbox + value=(readonly allowClearWithLabel) + onChange=(action (mut allowClearWithLabel))}} + Allow Clear + {{/paper-checkbox}} + +

Template

+ {{code-snippet name="autocomplete.floating-label.hbs"}} + + {{/paper-card-content}} + {{/paper-card}} {{/doc-content}} From 3ac1657e0cf21eea8e9149a376a98608efbbf9ab Mon Sep 17 00:00:00 2001 From: Andrey Khomenko Date: Tue, 10 Jul 2018 10:36:37 -0400 Subject: [PATCH 4/4] docs(...) paper-autocomplete with defaultHighlighted --- .../components/paper-autocomplete-trigger.js | 36 +++---------------- .../app/controllers/demo/autocomplete.js | 7 ++++ .../dummy/app/templates/demo/autocomplete.hbs | 6 ++++ 3 files changed, 17 insertions(+), 32 deletions(-) diff --git a/addon/components/paper-autocomplete-trigger.js b/addon/components/paper-autocomplete-trigger.js index e7a8f7e98..47177305d 100644 --- a/addon/components/paper-autocomplete-trigger.js +++ b/addon/components/paper-autocomplete-trigger.js @@ -3,9 +3,7 @@ */ import Component from '@ember/component'; import { not } from '@ember/object/computed'; -import { isBlank } from '@ember/utils'; -import { run } from '@ember/runloop'; -import { computed, get } from '@ember/object'; +import { computed } from '@ember/object'; import layout from '../templates/components/paper-autocomplete-trigger'; /** @@ -38,40 +36,14 @@ export default Component.extend({ // Lifecycle hooks didUpdateAttrs() { this._super(...arguments); - /* - * We need to update the input field with value of the selected option whenever we're closing - * the select box. But we also close the select box when we're loading search results and when - * we remove input text -- so protect against this - */ - let oldLastSearchedText = this.get('_lastSearchedText'); - let oldLoading = this.get('_loading'); - let oldDisabled = this.get('_lastDisabled'); - - let select = this.get('select'); - let loading = this.get('loading'); - let lastSearchedText = this.get('lastSearchedText'); + let prevDisabled = this.get('_prevDisabled'); let disabled = this.get('disabled'); - - if (lastSearchedText !== oldLastSearchedText) { - if (isBlank(lastSearchedText)) { - run.schedule('actions', null, select.actions.close, null, true); - } else { - run.schedule('actions', null, select.actions.open); - } - } else if (!isBlank(lastSearchedText) && get(this, 'options.length') === 0 && this.get('loading')) { - run.schedule('actions', null, select.actions.close, null, true); - } else if (oldLoading && !loading && this.get('options.length') > 0) { - run.schedule('actions', null, select.actions.open); - } - - if (oldDisabled && !disabled) { + if (prevDisabled && !disabled) { this.set('resetButtonDestroyed', false); } this.setProperties({ - _lastSearchedText: lastSearchedText, - _loading: loading, - _lastDisabled: disabled + _prevDisabled: disabled }); }, diff --git a/tests/dummy/app/controllers/demo/autocomplete.js b/tests/dummy/app/controllers/demo/autocomplete.js index 9b28cfdb0..bc19c1eb3 100644 --- a/tests/dummy/app/controllers/demo/autocomplete.js +++ b/tests/dummy/app/controllers/demo/autocomplete.js @@ -15,6 +15,13 @@ export default Controller.extend({ searchText: '', + highlightFirstMatch(api) { + if (api && api.results && api.results.length) { + return api.results[0]; + } + return null; + }, + actions: { updateFilter(str) { this.set('searchText', str); diff --git a/tests/dummy/app/templates/demo/autocomplete.hbs b/tests/dummy/app/templates/demo/autocomplete.hbs index b0de0bd5b..f5c9c3666 100644 --- a/tests/dummy/app/templates/demo/autocomplete.hbs +++ b/tests/dummy/app/templates/demo/autocomplete.hbs @@ -13,6 +13,7 @@ onCreate=(action "addCountry") options=items allowClear=true + defaultHighlighted=(if enableDefaultHighlighted highlightFirstMatch) searchText=(readonly countrySearchText) onSearchTextChange=(action (mut countrySearchText)) selected=selectedCountry @@ -47,6 +48,11 @@ onChange=(action (mut simulateQuery))}} Simulate query {{/paper-checkbox}} + {{#paper-checkbox + value=enableDefaultHighlighted + onChange=(action (mut enableDefaultHighlighted))}} + Highlight first match + {{/paper-checkbox}} {{paper-button primary=true label="Reset search-Text"