How to implement autosuggest using amp-list, amp-mustache, amp-form, and amp-bind?
would like to implement autosuggest
for intra-page search
have studied this Google example
would like autosuggest
to find US state capitals on a single page in this format
<div id='4'>Little Rock is ...</div>
our JSON structure looks like this
{
"items": [{
"query": "",
"results": [{"Montgomery, Alabama","id='1'"},
{"Juneau, Alaska","id='2'"},
{"Phoenix, Arizona","id='3'"},
{"Little Rock, Arkansas","id='4'"}]
}]
}
have implemented an MCV (minimal, complete, verifiable) example here
how to modify the example to navigate to a specific item on a page based on the selection in results-list?
Here's a quick summary of what you need to do
#2
will look like this
{{#results}}
<div
class='select-option no-outline'
role='option'
tabindex='0'
on='tap:autosuggest-list.hide,{{id}}.scrollTo'
option='{{title}}'
>{{title}}</div>
{{/results}}
Here is the specific build process (Steps A – D)
A. HTML and AMP code:
server endpoint
https://example.com/state_capitals/query
amp-form
<form
method='post'
action-xhr='https://example.com/state_capitals'
target='_blank'
id='search-form'
on='submit:autosuggest-list.hide;submit-success:results.show'
autocomplete='off'
>
HTML input
<div class='search-container'>
<input
id='query'
name='query'
type='text'
class='search-box'
on="input-debounced:AMP.setState({
query: event.value,
autosuggest: event.value
}),
autosuggest-list.show,
results.hide"
[value]="query || ''"
/>
<button class='search-submit' type='submit'>Search</button>
</div>
Above code sets Input Box
amp-list
next, bind results from '/state_capitals/query'
endpoint to amp-list
and amp-selector
components as below:
<amp-list
class='autosuggest-box'
layout='fixed-height'
height='120'
src='/state-capitals/query'
[src]="'/state-capitals/query?q=' + (autosuggest || '')"
id='autosuggest-list'
hidden
>
Source of the amp-list component is from the result of /state-capitals/query
in JSON
format.
JSON endpoint structure
{"items":[{
"query": "",
"results": [
{"title": "Little Rock, Arkansas", "id":"4"},
{"title": "Olympia, Washington", "id":"47"},
{"title": "Charleston, West Virginia", "id":"48"},
{"title": "Madison, Wisconsin", "id":"49"},
...
]}]}
amp-template
print result of JSON format using amp-mustache
component.
<amp-list ...>
<template type='amp-mustache'>
{{#results}}
<amp-selector
keyboard-select-mode='focus'
layout='container'
on='select:AMP.setState({query: event.targetOption}),
autosuggest-list.hide,{{id}}.scrollTo'
>
<div
class='select-option no-outline'
role='option'
tabindex='0'
on='tap:autosuggest-list.hide'
option='{{title}}'
>{{title}}</div>
{{/results}}
</amp-selector>
</template>
</amp-list>
Quick note about amp-selector
and on=
The following code:
on='select:AMP.setState({
query: event.targetOption}),
autosuggest-list.hide,{{id}}.scrollTo'
will scroll to:
{{id}}.scrollTo
Where the table row id, for example, is 107
<li><a href="1">Montgomery</a></li>
<li><a href="2">Juneau</a></li>
<li><a href="3">Phoenix</a></li>
<li><a href="4">Little Rock</a></li>
B. Endpoint implementation
Data = [
{"title": "Little Rock, Arkansas", "id":"4"},
...
{"title": "Olympia, Washington", "id":"47"},
{"title": "Charleston, West Virginia", "id":"48"},
{"title": "Madison, Wisconsin", "id":"49"},
];
app.use('/state_capitals/query', (req, res) => {
assertCors(req, res, ['GET']);
const MAX_RESULTS = 4;
const query = req.query.q;
if (!query) {
res.json({
items: [{
query: "",
results: capitals.slice(0, MAX_RESULTS)
}]
});
} else {
const lowerCaseQuery = query.toLowerCase();
const filtered = capitals.filter(function(e) {return e.title.toLowerCase().includes(lowerCaseQuery)});
res.json({
items: [{
query: "",
results: filtered.slice(0, MAX_RESULTS)
}]
});
}
});
C. NGINX settings
Node.js application runs on domain:< … > and specified port.
Ask Nginx to forward all traffic of port number 80 to a specified port when user runs your website in a browser. This is accomplished using location settings in conf file as
location /state_capitals/ {
proxy_pass http://domain:3002/;
}
D: Implementation