getaddress-nz-autocomplete
v2.0.0
Published
Drop-in New Zealand address, suburb and typeahead autocomplete for any text input. Attach it to a field you already have, and it fills the rest of your address form — no framework, no build step required. Powered by the getAddress() New Zealand address AP
Downloads
318
Maintainers
Readme
getaddress-nz-autocomplete
Drop-in New Zealand address autocomplete for any text input. Attach it to a field you already have and it fills the rest of your address form — no framework, no build step, no markup changes.
Addresses come from the getAddress() New Zealand address API, built on LINZ's NZ Addresses list (Toitū Te Whenua Land Information New Zealand), so every address point in New Zealand is covered and geocoded. Postcodes are unofficial — see Postcodes.
30-second start
<label for="address_line_1">Address line 1</label>
<input id="address_line_1" type="text">
<label for="address_line_2">Suburb</label>
<input id="address_line_2" type="text">
<label for="town_city">Town or city</label>
<input id="town_city" type="text">
<label for="postcode">Postcode</label>
<input id="postcode" type="text">
<script src="https://cdn.jsdelivr.net/npm/getaddress-nz-autocomplete@2/dist/getaddress-nz-autocomplete.browser.js"></script>
<script>
getAddressNz.autocomplete('address_line_1', 'YOUR-DOMAIN-TOKEN', {
output_fields: {
address_line_1: 'address_line_1',
address_line_2: 'address_line_2',
town_city: 'town_city',
postcode: 'postcode'
}
});
</script>That is the whole integration. Type 169 lambton into the first field, pick
"169 Lambton Quay, Wellington Central, Wellington 6011", and the rest fill in: 169 Lambton Quay,
Wellington Central, Wellington, 6011.
Install
npm install getaddress-nz-autocompleteimport { autocomplete } from 'getaddress-nz-autocomplete';
autocomplete('address_line_1', 'YOUR-DOMAIN-TOKEN', { /* options */ });Ships ESM, CommonJS, TypeScript types, and a <script src> build that puts getAddressNz on
window.
Use a domain token, not an API key
Anything in browser JavaScript is readable by anyone who opens the page. A domain token is restricted to the origins you list, so publishing it costs you nothing. An API key is not — keep it on your server.
Free vs metered
Suggestions are free and rate limited, so calling on every keystroke is fine. Only resolving a
picked suggestion to a full address counts as a look-up against your plan. If you only need the
printed line and not the parts, set enable_get: false and the widget never spends one.
Options
| Option | Default | What it does |
| --- | --- | --- |
| output_fields | – | Address fields to write into your form. Key is a field name, value is an element id, a CSS selector, or the element. |
| selected | – | Called with the full address once resolved. |
| suggestion_selected | – | Called the moment a suggestion is picked, before the look-up. |
| error | logs | Called when a request fails. |
| enable_get | true | Resolve the picked suggestion. false keeps the widget entirely free. |
| set_input_value | true | Write the picked address back into the attached input. |
| min_characters | 2 | Characters before the first request. |
| debounce_ms | 150 | Quiet period before a request is sent. Left unset, it lengthens on a slow connection (up to 500). Set it to fix the delay. |
| max_suggestions | 6 | Maximum suggestions shown. The API returns at most 6. |
| town_city | – | Restrict to one town or city, e.g. "Auckland". Sends the suggestion request as a POST. |
| postcode | – | Restrict to one postcode. Sends the suggestion request as a POST. |
| location | – | [latitude, longitude] to bias results towards. Nothing is excluded. |
| report_postcode_edits | false | Report a postcode the visitor corrects — see Postcodes. |
| google_places_fallback | true | Use the Google Places fallback when it is switched on in the console. false keeps this page on LINZ addresses only. |
| inject_styles | true | Inject the default stylesheet. |
| class_names | – | Override the class names on the elements the widget creates. |
| api_url | live API | Point at a different API origin. |
Address fields
output_fields keys are the API's own field names:
| Field | Example |
| --- | --- |
| id, address_id | 363752 — LINZ's address id, the one you pass to /get/{id} |
| address_label | 169 Lambton Quay, Wellington Central, Wellington 6011 — the whole address on one line |
| address_status | current, or retired once LINZ has withdrawn it |
| flat_number | 2 of 2/12 East Street |
| number_first | 48 of 48-56 Queen Street |
| number_last | 56 of 48-56 Queen Street |
| number_suffix | A of 12A Queen Street |
| full_road_name | Queen Street |
| locality_name | Auckland Central — the suburb |
| town_city | Auckland |
| territorial_authority | Selwyn District — the district or city council |
| postcode | 1010 — unofficial |
| postcode_source | how the postcode was assigned — see Postcodes |
latitude and longitude are accepted too, and reach into the address's coordinates (WGS84) — which is
null for an address with no position, in which case both fill with an empty string.
address_status is 'current' while LINZ still publishes the address, 'retired' once it has been
withdrawn. Nothing the widget suggests is ever retired, so it only matters if you resolve an id you stored earlier.
address_line_1 and address_line_2 are composed from the parts the way New Zealand writes an address:
address_line_1is the number and the road. A unit goes before the number with a slash, a suffix straight after it, and a range joins its ends with a hyphen:2/12 East Street,12A Queen Street,48-56 Queen Street,169 Lambton Quay. An address with no number is just its road.address_line_2is the suburb (locality_name), e.g.Auckland Central— or empty when the suburb is the town itself, as in808A Selwyn Road, Rolleston 7614, so the town is not written twice.
Wire town_city and postcode to their own fields. getAddressNz.addressLines(address) returns the same two
lines, for a selected callback.
Every field is a string, and is empty when that address has no value for it.
Postcodes
New Zealand postcodes here are unofficial: they come from the open_nz_postcodes project, not NZ Post, and
are wrong for roughly 5 addresses in 100. Every address says how its postcode was assigned in postcode_source:
| postcode_source | Meaning |
| --- | --- |
| road | from the road the address is on |
| suburb (single) | the suburb has one postcode |
| suburb (majority) | most of the suburb's addresses have it — lower confidence |
| none | no postcode could be assigned; postcode is empty |
| corrected | set from customers' corrections to this address |
| corrected (road) | set from customers' corrections to other addresses on the same road |
Turn on report_postcode_edits and the widget reports a postcode your visitor corrects:
getAddressNz.autocomplete('address_line_1', 'YOUR-DOMAIN-TOKEN', {
output_fields: { address_line_1: 'address_line_1', address_line_2: 'address_line_2', town_city: 'town_city', postcode: 'postcode' },
report_postcode_edits: true
});It watches the field wired to output_fields.postcode. When the visitor picks an address and then changes the
filled postcode to a different four-digit one before submitting the form (or, outside a form, leaving the field),
the widget sends it to POST /postcode-correction/{id}. Reports are free, are weighed at a weekly run rather
than applied at once, and never interrupt the page if they fail. It is off by default.
Events
If callbacks do not suit, listen on the input instead:
const instance = getAddressNz.autocomplete('address_line_1', 'YOUR-DOMAIN-TOKEN');
instance.addEventListener('getaddress-nz-autocomplete-address-selected', e => {
console.log(e.address);
});| Event | Fires | Carries |
| --- | --- | --- |
| getaddress-nz-autocomplete-suggestions | each time a new list of suggestions arrives | e.suggestions |
| getaddress-nz-autocomplete-suggestion-selected | the moment a suggestion is picked | e.suggestion |
| getaddress-nz-autocomplete-address-selected | once the picked suggestion is resolved | e.address, e.suggestion |
| getaddress-nz-autocomplete-address-selected-failed | when resolving fails, e.g. a 429 | e.error, e.suggestion |
The same values are on e.detail too.
Show the address as JSON
The pattern the getAddress() home page uses — a search box, and the chosen address printed below:
const input = document.getElementById('autocomplete-textbox');
const viewer = document.getElementById('json-viewer');
getAddressNz.autocomplete(input, 'YOUR-DOMAIN-TOKEN', { set_input_value: false });
input.addEventListener('getaddress-nz-autocomplete-suggestions', () => viewer.textContent = '');
input.addEventListener('getaddress-nz-autocomplete-address-selected', e => {
viewer.textContent = JSON.stringify(e.address, null, 2);
input.value = '';
});
input.addEventListener('getaddress-nz-autocomplete-address-selected-failed', e => {
viewer.textContent = e.error.message;
});Suburbs and postcodes: location()
The same package suggests places — one per suburb, town and postcode — for a place picker rather than
an address form. Picking one resolves its centre (one look-up; enable_get: false keeps it free).
<input id="suburb" type="text">
<input id="town_city" type="text">
<input id="postcode" type="text">
<script>
getAddressNz.location('suburb', 'YOUR-DOMAIN-TOKEN', {
output_fields: { locality_name: 'suburb', town_city: 'town_city', postcode: 'postcode' },
selected: place => console.log(place.coordinates) // { latitude, longitude }
});
</script>A place's id is suburb|town|postcode, e.g. Normanby|Hāwera|4614, and its label reads
Normanby, Hāwera 4614 (Rolleston 7614 when the suburb is the town). It takes the same options as
autocomplete() bar the address-only ones (google_places_fallback, report_postcode_edits) — town_city
and postcode restrict it — with output_fields keys id, location, locality_name, town_city,
territorial_authority, postcode, latitude and longitude. Its events are getaddressnz-location-suggestions, getaddressnz-location-suggestion-selected,
getaddressnz-location-selected (event.location is the place) and getaddressnz-location-selected-failed.
Form fields that complete themselves: typeahead()
Any single field — a suburb, a town or city, or a postcode — completes as it is typed. It suggests plain values, not addresses, so it is free: it never spends a look-up.
<input id="suburb" type="text">
<input id="town_city" type="text">
<script>
// Each field completes on its own.
getAddressNz.typeahead('suburb', 'YOUR-DOMAIN-TOKEN', { search: 'locality' });
getAddressNz.typeahead('town_city', 'YOUR-DOMAIN-TOKEN', { search: 'town_city' });
</script>search is 'locality', 'town_city' or 'postcode', or an array of them. filter narrows the values to
addresses matching town_city, locality and postcode — { town_city: 'Hāwera' } completes only Hāwera's
suburbs. Macrons are optional when typing: hawera finds Hāwera. Events: getaddressnz-typeahead-suggestions and
getaddressnz-typeahead-selected (event.value).
Checking a whole address: validate()
For an address that arrives on one line — pasted, imported, or typed into a single box — validate() confirms it
against the LINZ address list. It is a promise, not a widget.
const result = await getAddressNz.validate('169 Lambton Quay, Wellington 6011', 'YOUR-DOMAIN-TOKEN');
if (result.status === 'found') {
console.log(result.address.address_label); // one look-up
} else if (result.status === 'ambiguous') {
console.log(result.candidates); // ids — free
}Reverse geocoding: nearest()
The addresses nearest a point, nearest first, each with its distance in metres — for a map pin or a "use my location"
button. top defaults to 1 (max 20) and radius to 0.2 km (max 1). One look-up when it finds an address; nothing in
reach is an empty list and costs nothing.
const [here] = await getAddressNz.nearest(-41.2828, 174.7760, 'YOUR-DOMAIN-TOKEN', { top: 1, radius: 0.2 });
if (here) {
console.log(here.address, here.distance); // e.g. "169 Lambton Quay, Wellington Central, Wellington 6011" — pass here.id to /get for the rest
}Distance: distance()
Straight-line metres between two addresses or locations (their ids, in any mix) or two points ([latitude, longitude]). Free; it answers
metres and never coordinates.
// Two address ids, two location ids, or one of each.
const metres = await getAddressNz.distance('363752', '1131927', 'YOUR-DOMAIN-TOKEN');Frameworks
It attaches to an element, so it works with React, Vue, Svelte or plain HTML. Every field it writes
dispatches input and change, so framework-bound state updates rather than silently keeping the
old value. Call destroy() when your component unmounts.
Styling
The default stylesheet is injected once and is deliberately minimal. Override the custom properties (the
--gaau- prefix is kept from earlier versions so existing overrides keep working):
.getaddress-nz-autocomplete {
--gaau-bg: #fff;
--gaau-border: #d7d9e3;
--gaau-text: #1f2033;
--gaau-hover-bg: #f2f3f9;
--gaau-match: #4338ca;
--gaau-radius: 6px;
}Or pass inject_styles: false and write your own against .getaddress-nz-autocomplete,
.getaddress-nz-autocomplete__item, .getaddress-nz-autocomplete__item--selected and
.getaddress-nz-autocomplete__match.
Dark mode follows prefers-color-scheme unless you set data-gaau-theme="light" on the list.
Accessibility
The input is marked up as a combobox with an owned listbox, options are exposed with
aria-selected, and the highlighted option is tracked with aria-activedescendant. Arrow keys
move, Enter selects, Escape closes. Enter is only intercepted while an option is highlighted, so it
still submits your form otherwise.
Development
npm install
npm run buildThen open test/index.html, paste a key, and try it.
Licence
MIT © getAddress()
The MIT licence covers the code only. Addresses are sourced from the LINZ Data Service and licensed for reuse under the CC BY 4.0 licence. Postcodes come from the open_nz_postcodes project (CC0) and are not NZ Post's.
