Skip to content

Commit

Permalink
✨ [amp-autocomplete] Add support for prefetch attribute for prefetc…
Browse files Browse the repository at this point in the history
…hing remote data (ampproject#31021)

* Add support for `prefetch` attribute

* Update validation rules and add test

* Update validator-amp-autocomplete.out

* Address code review comments
  • Loading branch information
dmanek authored and ed-bird committed Dec 10, 2020
1 parent cd5f393 commit edfb01b
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 8 deletions.
20 changes: 12 additions & 8 deletions extensions/amp-autocomplete/0.1/amp-autocomplete.js
Expand Up @@ -220,14 +220,14 @@ export class AmpAutocomplete extends AMP.BaseElement {
this.viewport_ = null;

/** @private {boolean} */
this.interacted_ = false;
this.hasFetchedInitialData_ = false;

/**
* To ensure that we provide an accessible experience,
* the suggestion container must have a unique ID.
* In case the autocomplete doesn't have an ID we use a
* random number to ensure uniqueness.
@private {number|string}
@private {number|string}
*/
this.containerId_ = element.id
? element.id
Expand Down Expand Up @@ -499,6 +499,10 @@ export class AmpAutocomplete extends AMP.BaseElement {
// Disable autofill in browsers.
this.inputElement_.setAttribute('autocomplete', 'off');

if (this.element.hasAttribute('prefetch')) {
this.checkFirstInteractionAndMaybeFetchData_();
}

// Register event handlers.
this.inputElement_.addEventListener(
'touchstart',
Expand Down Expand Up @@ -687,19 +691,19 @@ export class AmpAutocomplete extends AMP.BaseElement {
*/
autocomplete_(data, opt_input = '') {
this.clearAllItems_();
if (opt_input.length < this.minChars_ || !data) {
if (!data || opt_input.length < this.minChars_) {
return Promise.resolve();
} else if (this.isSsr_) {
}
if (this.isSsr_) {
return hasOwn(data, 'html')
? this.renderResults_(
data,
dev().assertElement(this.container_),
opt_input
)
: Promise.resolve();
} else {
return this.filterDataAndRenderResults_(data, opt_input);
}
return this.filterDataAndRenderResults_(data, opt_input);
}

/**
Expand Down Expand Up @@ -990,10 +994,10 @@ export class AmpAutocomplete extends AMP.BaseElement {
* @private
*/
checkFirstInteractionAndMaybeFetchData_() {
if (this.interacted_ || !this.element.hasAttribute('src')) {
if (this.hasFetchedInitialData_ || !this.element.hasAttribute('src')) {
return Promise.resolve();
}
this.interacted_ = true;
this.hasFetchedInitialData_ = true;
return this.getRemoteData_().then(
(remoteData) => {
this.sourceData_ = remoteData;
Expand Down
21 changes: 21 additions & 0 deletions extensions/amp-autocomplete/0.1/test/test-amp-autocomplete-init.js
Expand Up @@ -318,6 +318,27 @@ describes.realWin(
});
});

it('should prefetch remote data if prefetch attribute is specified', () => {
let impl;
return getAutocomplete(
{
'prefetch': '', // boolean attribute, presence means prefetch is enabled.
'src': 'https://examples.com/json',
'filter': 'substring',
},
'{}',
false
)
.then((ampAutocomplete) => {
impl = ampAutocomplete.implementation_;
expect(impl.hasFetchedInitialData_).to.be.false;
return ampAutocomplete.layoutCallback();
})
.then(() => {
expect(impl.hasFetchedInitialData_).to.be.true;
});
});

it('should not fetch remote data when specified in src and using nested items property before first user interactino', () => {
const data = {
deeply: {
Expand Down
Expand Up @@ -588,5 +588,23 @@
<amp-autocomplete filter="prefix" query="q">
<input />
</amp-autocomplete>

<!-- Valid: amp-component with remote data, filter=prefix and prefetch attribute -->
<amp-autocomplete
filter="prefix"
src="https://data.com/articles.json?ref=CANONICAL_URL"
prefetch
>
<input />
</amp-autocomplete>

<!-- Invalid: prefetch is mistyped -->
<amp-autocomplete
filter="prefix"
src="https://data.com/articles.json?ref=CANONICAL_URL"
prefecth
>
<input />
</amp-autocomplete>
</body>
</html>
Expand Up @@ -609,5 +609,25 @@ amp-autocomplete/0.1/test/validator-amp-autocomplete.html:580:4 The attribute 'f
amp-autocomplete/0.1/test/validator-amp-autocomplete.html:588:4 The attribute 'src' in tag 'amp-autocomplete' is missing or incorrect, but required by attribute 'query'. (see https://amp.dev/documentation/components/amp-autocomplete/)
| <input />
| </amp-autocomplete>
|
| <!-- Valid: amp-component with remote data, filter=prefix and prefetch attribute -->
| <amp-autocomplete
| filter="prefix"
| src="https://data.com/articles.json?ref=CANONICAL_URL"
| prefetch
| >
| <input />
| </amp-autocomplete>
|
| <!-- Invalid: prefetch is mistyped -->
| <amp-autocomplete
>> ^~~~~~~~~
amp-autocomplete/0.1/test/validator-amp-autocomplete.html:602:4 The attribute 'prefecth' may not appear in tag 'amp-autocomplete'. (see https://amp.dev/documentation/components/amp-autocomplete/)
| filter="prefix"
| src="https://data.com/articles.json?ref=CANONICAL_URL"
| prefecth
| >
| <input />
| </amp-autocomplete>
| </body>
| </html>
4 changes: 4 additions & 0 deletions extensions/amp-autocomplete/amp-autocomplete.md
Expand Up @@ -198,6 +198,10 @@ Specifies the key to the data array within the JSON response. Nested keys can be

Whether the <code>amp-autocomplete</code> should autosuggest on the full user input or only a triggered substring of the user input. By default when the attribute is absent, suggestions will be based on the full user input. The attribute cannot have an empty value but must take a single character token, i.e. <code>@</code> which activates the autocomplete behavior. For example, if <code>inline="@"</code> then user input of <code>hello</code> will not retrieve suggestions but a user input of <code>hello @abc</code> might trigger options filtered on the substring <code>abc</code>. Currently triggered substrings are delimited on whitespace characters, however this is subject to change in the future.

### `prefetch`

Include the `prefetch` attribute to prefetch remote data to improve responsiveness for users. Requires `src` to be specified.

## Events

### `select`
Expand Down
Expand Up @@ -65,6 +65,7 @@ tags: { # <amp-autocomplete>
attrs: { name: "max-entries" }
attrs: { name: "max-items" }
attrs: { name: "min-characters" }
attrs: { name: "prefetch" }
attrs: {
name: "query"
trigger: {
Expand Down Expand Up @@ -107,6 +108,7 @@ tags: { # <amp-autocomplete>
attrs: { name: "items" }
attrs: { name: "max-items" }
attrs: { name: "min-characters" }
attrs: { name: "prefetch" }
attrs: {
name: "query"
trigger: {
Expand Down

0 comments on commit edfb01b

Please sign in to comment.