I am using Airship and carto-vl while working through this tutorial and the values in the widget are coming back as NaN. Here is my code:

<!DOCTYPE html>

  <!-- Include CSS elements -->
  <link rel="stylesheet" href="https://libs.cartocdn.com/airship-style/v1.0.3/airship.css">
  <!-- Include icons -->
  <link rel="stylesheet" href="https://libs.cartocdn.com/airship-icons/v1.0.3/icons.css">
  <!-- Include airship components -->
  <script src="https://libs.cartocdn.com/airship-components/v1.0.3/airship.js"></script>
  <!-- Include Mapbox GL JS -->
  <script src="https://libs.cartocdn.com/mapbox-gl/v0.48.0-carto1/mapbox-gl.js"></script>
  <!-- Include Mapbox GL CSS -->
  <link href="https://libs.cartocdn.com/mapbox-gl/v0.48.0-carto1/mapbox-gl.css" rel="stylesheet" />
  <!-- Include CARTO VL JS -->
  <script src="https://libs.cartocdn.com/carto-vl/v1.1.1/carto-vl.min.js"></script>
  <title>Airship Testing</title>

<body class="as-app-body">
  <div class="as-app">
    <div class="as-content">
      <main class="as-main">
        <div class="as-map-area">
          <div id="map"></div>
      <aside class="as-sidebar as-sidebar--right">
        <as-category-widget id="cities-widget" heading="Populated places" description="Maximun population of the most pouplated cities">

  <!-- CARTO basemap -->
    const map = new mapboxgl.Map({
      container: 'map',
      style: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',
      center: [0, 30],
      zoom: 2,
      scrollZoom: true,
      dragRotate: false,
      touchZoomRotate: false

    // Define user
      user: 'cartovl',
      apiKey: 'default_public'

    // Define layer
    const source = new carto.source.Dataset('ne_10m_populated_places_simple');
    const viz = new carto.Viz(`
      @cities: viewportFeatures($pop_max, $name)
    const layer = new carto.Layer('layer', source, viz);

    const $categoryWidget = document.querySelector('#cities-widget');

    function updateWidgets() {
      $categoryWidget.categories = viz.variables.cities.value
        .map(feature => ({
          name: feature.name,
          value: feature.pop_max,
        .sort((a, b) => b.value - a.value);


    layer.on('updated', updateWidgets);
    layer.addTo(map, 'watername_ocean');


Here is what the app looks like:

carto page

Why are the values of the table not returning?

I thought there might be a bug in the tutorial, but I transferred the same methodologies over to a personal project and I got the same results.


As you mention, the tutorial has a mistake. You're not getting the properties from the feature in the loop correctly. The code from the example is:

$categoryWidget.categories = viz.variables.cities.value
  .map(feature => ({
    name: feature.name,
    value: feature.pop_max,
  .sort((a, b) => b.value - a.value);

This is wrong. If you take a look to the feature object in the loop, you'll see that the nameand pop_max are not in the feature, but in the feature.properties. Therefore, the correct code is:

$categoryWidget.categories = viz.variables.cities.value
  .map(feature => ({
    name: feature.properties.name,
    value: feature.properties.pop_max,
  .sort((a, b) => b.value - a.value);

working example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.