Address-[auto]complete

Anton Korzunov
React Camp
Published in
5 min readDec 13, 2017

All the good sited has a good forms. And all the good forms has an address field you have to fill. But not all address fields are good.

And all the good stories has a beginning, and this one also does. In the beginning was a twitt. And it was good.

And next 2 things happens:

— I’ve feel that I have to test Downshift. I want to tests it from the time it was born, and never got a time for it. I am making selects with autocomplete since 2008, and I have to test this brand new one!

— I’ve spot a magic word — address autocomplete. It is just quite magical for me — I was a Maps API developer for 6 years, and was just involved into bunch or cartographical solutions last 10 years.

IFYI: Also I am a creator of a Wikimapia rendering engine, and I am a formal owner of another cartographical site with a few millions users per month.

Thus means — I have to publish a good, or just better solution around this problem in open source. Who else?

The Task

Anyway — to create a good address autocomplete form you have to acomplish 2 tasks:

  • Create an address autocomplete field
  • Create a country/state selector with proper foreign keys.

Autocomplete

First may sounds easy — just ask some cartographical provider to geocode an address, and display the results.

You can use Google geocoder or Google places API, or something else by Google, but I will suggest to use a better thing — OpenStreetMap based solution from MapZen — Pelias.

From one point of view — it is quite cheap, from another — it is actually open source, and you can run your own server for free.

And quality, from some point of view, is even better than Google could provide. But there is a little problem.

The foreign keys

MapZen can give you a textural explanation of an address. MapZen can give you an iso3166–1 code of a country(like US), but — it will be in a 3 letters form(like USA), and there is no iso3166–2 code for a region (issue).

If you want a good form, you have to submit a country in a 2 letters form (US, FR, RU, CA), and also provide a 2 letter code for a state (FR-J, US-NY, RU-MOS, AU-NSW and so on).

So you have to have a mapping from ISO3 codes to ISO2 codes, and you also have to have a mapping from “whosonfirst-data”(internal Mapzen/Pelias database) to a more standard codes.

And which codes are standard?

  • iso3166–2 code. The primary code for a state.
  • OpenStreetMap relation id. The more and more sources are based on OSM
  • geonames. Just a common database.
  • whosonfirst. Already a standard.
  • statoids. Unfortunately, literally dead.
  • wikipedia. Anything, including states, got a wikipedia article, btw.

And there is a library, which could provide mapping between all these sources

Hooray!?

So problem is solved, I’ve tested it on local and next one could create a little test on CodeSandbox.io to demo this stuff to a friends.

The brand new library to handle all the autocomplete-about stuff is quite simple, and quite handy. You probably could like it

…but after 5 minutes CodeSandbox is still loading something, and nothing seems to work.

WFT?!!!!!!!

“Optimization”

iso3166–2 contain all* counties with all** states in all*** languages. The size of result package is over 4Mb. So one day I’ve decided to optimize it a bit, and “optimize” it quite well…

PS: Each * indicates “how all” it is in real. Nothing is perfect

Address-complete need just a 2 small mapping files, but have to download 100500 more files first. About 120Mb.

It was an epic fail.

But Kent C. Dodds saved me once again. Not personaly, he just created preval — small babel plugin to pre-`eval` code on build step.

Using this magic wand, I’ve just added 2 comments to my imports, and thus allow me to move iso3166–2-db from deps to dev-deps, as bundle in production build just what I want to bundle.

import ISO3TOISO2 from /* preval */ 'iso3166-2-db/mapping/ISO3TO2';
import woff2iso from /* preval */ 'iso3166-2-db/mapping/woff2iso'

As result — address-complete demo could be run inside CodeSandbox! At last!

Downshift

As I said — I was doing and using “selects” with autocomplete since 2008. Downshift is not the best, mainly cos it is not autocompletable select, but controller for a select.

Also most examples are not quite semantically and a11y correct, as long create markup for a select is a your duty, and people just use divs, without any roles, in the end.

It should be OL:LI, or divs with roles listbox/option. Or both. There is no universal silver bullet.

It is not easy to use it, but it allows you to do — everything. ❤️

The end?

But all good forms should not only contain address-complete — they may also contain country, state, city fields. And you have to fill them correctly.

Address-complete as a library does provide all this information, but country and state should be a selects, and this requires you to populate them with correct values.

My yesterdays advice will be simple

— Duh, just use iso3166–2-db, and be happy.

I did not measure the package size yesterday, only the target side, effective for a customer.

Today I could say it a bit different — use “the-country-names” if you need all countries in English and for Western world(UN point of view). And use iso3166–2-db if you need “everything bigger”.

the-country-names is just a 30kb extraction from iso3166–2-db, but it can help a lot, making possible to run the example inside the CodeSandbox.

The result

And here is the result. In a form of example on CodeSandbox with:

  • country selector
  • state-for-a-country selector
  • address auto complete
  • and address auto-populate

I’ll hope this small example and some tooling around will help someone to make the forms better.

Big thanks to:

Kent C. Dodds for `downshift`, `preval` and inspiring.

Ives van Hoorne for CodeSandbox. (and codesandbox-driven-developement)

— all the people from MapZen. You are the only API I am happy to work with.

PS: address-complete also supports Google and Yandex geocoders, but only on serverside for a while.

PPS: As the-country-list was generated from iso3166–2-db, iso3166–2 was generated from another package — OSMe. And it also provides a geometry for a administrative divisions of a world.

--

--