alphagov / govuk-country-and-territory-autocomplete

An autocomplete widget that uses data from Country and Territory Register.
https://alphagov.github.io/govuk-country-and-territory-autocomplete/examples/
MIT License
38 stars 18 forks source link

Fix preselected values causing undefined errors #66

Closed jonheslop closed 5 years ago

jonheslop commented 5 years ago

Prefilled result is passed to the template as a string not an object

So we need to add a check to see if is an object else use the string

Which fixes https://github.com/alphagov/accessible-autocomplete/issues/383

NickColley commented 5 years ago

I think this is indeed the right place to be thinking of a fix, since the 'undefined' value was always in the list but the thing that has changed upstream is:

the menu opens when the user types something that is not within the list of options, so because a country name is not equal to 'undefined' the previously hidden option is now open.

NickColley commented 5 years ago

Spoke to Jon and he's happy for me to pick this up and get it shipped.

NickColley commented 5 years ago

Tip for anyone else who wants a good JavaScript error stack trace

  1. run npm run build
  2. run npx http-server
  3. go to http://127.0.0.1:8080/examples/

For some reason the dev build stack traces swallow the original location so it's hard to know what has broken.

NickColley commented 5 years ago

I've figured it out, the inputValue template needs to handle this change in data structure too.

I wonder if there's a sensible way to fallback if these templates fail upstream, maybe to fallback to not templating?

NickColley commented 5 years ago

I think for now we'll go with the downstream fixes, but if this comes up again for other users downstream, we can do something like this upstream:


  // This template is used when converting from a state.options object into a state.query.
  templateInputValue (value) {
    const inputValueTemplate = this.props.templates && this.props.templates.inputValue
    var templatedValue
    // Check that the template is a function that we can use
    if (typeof inputValueTemplate === 'function') {
      templatedValue = inputValueTemplate(value)
    }
    // Check that the templated value is not undefined
    return typeof templatedValue !== 'undefined' ? templatedValue : value
  }

  // This template is used when displaying results / suggestions.
  templateSuggestion (value) {
    const suggestionTemplate = this.props.templates && this.props.templates.suggestion
    var templatedSuggestion
    // Check that the template is a function that we can use
    if (typeof suggestionTemplate === 'function') {
      templatedSuggestion = suggestionTemplate(value)
    }
    // Check that the templated value is not undefined
    return typeof templatedSuggestion !== 'undefined' ? templatedSuggestion : value
  }

Perhaps there's some issues with the inputValue template not being applied to the defaultValue until the user interacts by typing too.

jonheslop commented 5 years ago

Nice one Nick, just tried it out and its working 🙌