javascriptgoogle-visualizationpolymerpolymer-1.0geomap

Polymer 1.x: Geomap Reentrancy


I want to get this geomap to behave properly. States start disappearing after the user presses the Select All button. What is the fix?

To recreate the problem, follow these steps:

  1. Open this jsBin.
  2. Click the Select All button.
  3. Hover your mouse over the state of Alaska.
  4. Notice the hover text including the state name appear when the focus is on Alaska.
  5. Select the state of Alaska.
  6. ❌ Notice the fill color turned white.
  7. ❌ Notice there is no longer any hover text on focus for the selected state.
  8. ❌ Try to select it again. Notice nothing happens.
  9. Repeat by selecting other states.
  10. Click the Clear All button.
  11. ❌ Notice the previously selected states are white and have no hover focus whereas their neighbors have fill colors of grey and do have hover text.
http://jsbin.com/ponayajifo/1/edit?html,console,output
<!DOCTYPE html>

<head>
  <meta charset="utf-8">
  <base href="https://polygit.org/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link href="polymer/polymer.html" rel="import">
  <link href="google-chart/google-chart.html" rel="import"> </head>

<body>
  <dom-module id="x-element">
    <template>
      <style>
        google-chart {
          width: 100%;
        }
      </style>
      <br><br><br><br>
      <button on-tap="_show">Show Values</button>
      <button on-tap="clearAll">Clear All</button>
      <button on-tap="selectAll">Select All</button>
      <div>[[selectedString]]</div>
      <google-chart id="geochart"
                    type="geo"
                    options="[[options]]"
                    data="[[data]]"
                    on-google-chart-select="_onGoogleChartSelect">
      </google-chart>
    </template>
    <script>
      (function() {
        // Monkey patch for google-chart
        var gcp = Object.getPrototypeOf(document.createElement('google-chart'));
        gcp.drawChart = function() {
          if (this._canDraw) {
            if (!this.options) {
              this.options = {};
            }
            if (!this._chartObject) {
              var chartClass = this._chartTypes[this.type];
              if (chartClass) {
                this._chartObject = new chartClass(this.$.chartdiv);
                google.visualization.events.addOneTimeListener(this._chartObject,
                    'ready', function() {
                        this.fire('google-chart-render');
                    }.bind(this));
                google.visualization.events.addListener(this._chartObject,
                    'select', function() {
                        this.selection = this._chartObject.getSelection();
                        this.fire('google-chart-select', { selection: this.selection });
                    }.bind(this));
                if (this._chartObject.setSelection){
                  this._chartObject.setSelection(this.selection);
                }
              }
            }
            if (this._chartObject) {
              this._chartObject.draw(this._dataTable, this.options);
            } else {
              this.$.chartdiv.innerHTML = 'Undefined chart type';
            }
          }
        };
        Polymer({
          is: 'x-element',
          /** /
           * Fired when user selects chart item.
           *
           * @event us-map-select
           * @param {object} detail Alpabetized array of selected state names.
          /**/
          properties: {
            items: {
              type: Array,
              value: function() {
                return [ 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming', ].sort();
              },
            },
            color: {
              type: String,
              value: 'blue',
            },
            options: {
              type: Object,
              computed: '_computeOptions(color)',
            },
            selected: {
              type: Array,
              value: function() {
                return [];
              }
            },
            data: {
              type: Array,
              computed: '_computeData(items, selected.length)'
            },
            selectedString: {
              type: String,
              computed: '_computeSelectedString(selected.length)',
            },
          },
          _computeOptions: function() {
            return {
              region: 'US',
              displayMode: 'regions',
              resolution: 'provinces',
              legend: 'none',
              defaultColor: 'white',
              colorAxis: {
                colors: ['#E0E0E0', this.color],
                minValue: 0,  
                maxValue: 1,
              }
            }
          },    
          // On select event, compute 'selected'
          _onGoogleChartSelect: function(e) {
            var string = e.path[0].textContent.split('Select')[0].trim(), // e.g. 'Ohio'
                selected = this.selected, // Array of selected items
                index = selected.indexOf(string);
            // If 'string' is not in 'selected' array, add it; else delete it
            if (index === -1) {
              this.push('selected', string);
            } else {
              this.splice('selected', index, 1);
            }
          },
          _computeSelectedString: function(selectedInfo) {
            return this.selected.sort().join(', ');
          },
          // After 'items' populates or 'selected' changes, compute 'data'
          _computeData: function(items, selectedInfo) {
            var data = [],
                selected = this.selected,
                i = items.length;
            while (i--) {
              data.unshift([items[i], selected.indexOf(items[i]) > -1 ? 1 : 0]);
            }
            data.unshift(['State', 'Select']);
            return data;
          },
          clearAll: function() {
            this.set('selected', []);
          },
          selectAll: function() {
            this.set('selected', this.items);
          },
          _show: function() {
            //console.log('items', this.items);
            console.log('selected', this.selected);
            //console.log('data', this.data);
          },
        });
      })();
    </script>
  </dom-module>
  <x-element color="red" selected='["Colorado", "South Dakota"]'></x-element>
</body>

</html>

Solution

  • The problem is in the selectAll function

      selectAll: function() {
            this.set('selected', this.items.slice());
      }
    

    I added this.items.slice(). otherwise the select event is not fire..

    http://jsbin.com/roxowoyupo/edit?html,console,output