Let Me Tink About It
Let Me Tink About It

Reputation: 16112

Polymer 1.x: Data binding

I want to select states in the <google-chart> geo map element shown in this jsBin.

When I select a state, I expect it to change color (to dark teal) but instead, it stays the same color (light grey).

Follow these steps to recreate the problem:

  1. Open this jsBin.
  2. In the section dom-module > <script> > properties > items > value, change the array ['Alabama', 0] to ['Alabama', 1].
  3. Notice the state of Alabama changes color from light grey to dark teal.
  4. Hover your mouse over the state of Alabama.
  5. Notice the value of the Select variable is 1 for the state of Alabama (and 0 for all the other states).
  6. Return the value of the array to ['Alabama', 0].
  7. Note the previous step proves the code generating the geochart behaves as expected when the items property is manually mutated.
  8. Here's where the trouble begins...
  9. Click the state of Alabama.
  10. In the console, notice the value of the items[1] array is ['Alabama', 1].
  11. Notice the Select value is 0 (unlike the case when we manually changed it above).

What could be the problem here?

I'm uncertain but perhaps the solution involves properly implementing this advice?

When handling events generated by a dom-repeat template instance, you frequently want to map the element firing the event to the model data that generated that item.

But how does one implement that solution in this case? Or is that even the solution?

What is the solution? Please show it working in a jsBin.

http://jsbin.com/pilotazifa/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%;
          max-height: 300px;
        }
      </style>
      <button on-tap="_show">Show</button>
      <google-chart
        id="geochart"
        type="geo"
        options={{options}}
        data={{items}}
        on-google-chart-select="_onGoogleChartSelect"
      ></google-chart>
    </template>

    <script>
      (function(){
        Polymer({
          is: 'x-element',
          properties: {
            items: {
              type: Array,
              notify: true,
              reflectToAttribute: true,
              value: function() {
                return [['State', 'Select'], ['Alabama', 0], ['Alaska', 0], ['Arizona', 0], ['Arkansas', 0], ['California', 0], ['Colorado', 0], ['Connecticut', 0], ['Delaware', 0], ['Florida', 0], ['Georgia', 0], ['Hawaii', 0], ['Iowa', 0], ['Idaho', 0], ['Illinois', 0], ['Indiana', 0], ['Kansas', 0], ['Kentucky', 0], ['Louisiana', 0], ['Massachusetts', 0], ['Maryland', 0], ['Maine', 0], ['Michigan', 0], ['Minnesota', 0], ['Missouri', 0], ['Mississippi', 0], ['Montana', 0], ['North Carolina', 0], ['North Dakota', 0], ['Nebraska', 0], ['New Hampshire', 0], ['New Jersey', 0], ['New Mexico', 0], ['Nevada', 0], ['New York', 0], ['Ohio', 0], ['Oklahoma', 0], ['Oregon', 0], ['Pennsylvania', 0], ['Rhode Island', 0], ['South Carolina', 0], ['South Dakota', 0], ['Tennessee', 0], ['Texas', 0], ['Utah', 0], ['Virginia', 0], ['Vermont', 0], ['Washington', 0], ['Wisconsin', 0], ['West Virginia', 0], ['Wyoming', 0]];
              }
            },
            options: {
              type: Object,
              notify: true,
              reflectToAttribute: true,
              value: function() {
                return {
                  region: 'US',
                  displayMode: 'regions',
                  resolution: 'provinces',
                  legend: 'none',
                  defaultColor: '#F5F5F5',
                  colorAxis: {
                    colors: ['#F5F5F5', '#455A64'],
                    minValue: 0,  
                    maxValue: 1,
                  }
                }
              }
            },
          },

          _onGoogleChartSelect: function(e) {
            var str = e.path[0].textContent.split('Select')[0].trim(),
                ar = this.items,
                i = ar.length;
            while(i---1){
              if(str === ar[i][0]){
                this.set('items.' + i + '.1', ar[i][1] ? 0 : 1);
              }
            }
            console.log(this.items);
          },
          _show: function() {
            console.log(this.items);
          },
        });
      })();
    </script>

  </dom-module>

  <x-element></x-element>

</body>
</html>

Upvotes: 1

Views: 69

Answers (2)

Let Me Tink About It
Let Me Tink About It

Reputation: 16112

The complete text of the solution by @Alon is as follows:

http://jsbin.com/redaqezare/1/edit?html,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%;
          max-height: 300px;
        }
      </style>
      <google-chart
        id="geochart"
        type="geo"
        options={{options}}
        data={{items}}       
      ></google-chart>
    </template>

    <script>
      (function(){
        Polymer({
          is: 'x-element',
          ready:function(){
            this.items=[['State', 'Select'], ['Alabama', 0], ['Alaska', 0], ['Arizona', 0], ['Arkansas', 0], ['California', 0], ['Colorado', 0], ['Connecticut', 0], ['Delaware', 0], ['Florida', 0], ['Georgia', 0], ['Hawaii', 0], ['Iowa', 0], ['Idaho', 0], ['Illinois', 0], ['Indiana', 0], ['Kansas', 0], ['Kentucky', 0], ['Louisiana', 0], ['Massachusetts', 0], ['Maryland', 0], ['Maine', 0], ['Michigan', 0], ['Minnesota', 0], ['Missouri', 0], ['Mississippi', 0], ['Montana', 0], ['North Carolina', 0], ['North Dakota', 0], ['Nebraska', 0], ['New Hampshire', 0], ['New Jersey', 0], ['New Mexico', 0], ['Nevada', 0], ['New York', 0], ['Ohio', 0], ['Oklahoma', 0], ['Oregon', 0], ['Pennsylvania', 0], ['Rhode Island', 0], ['South Carolina', 0], ['South Dakota', 0], ['Tennessee', 0], ['Texas', 0], ['Utah', 0], ['Virginia', 0], ['Vermont', 0], ['Washington', 0], ['Wisconsin', 0], ['West Virginia', 0], ['Wyoming', 0]];
            var _this=this; 
            this.$.geochart.addEventListener('google-chart-select',function(e){this._onGoogleChartSelect(e)}.bind(_this));
          },
          properties: {
            items: {
              type: Array,
              notify: true,
              reflectToAttribute: true
            },
            options: {
              type: Object,
              notify: true,
              reflectToAttribute: true,
              value: function() {
                return {
                  region: 'US',
                  displayMode: 'regions',
                  resolution: 'provinces',
                  legend: 'none',
                  defaultColor: '#F5F5F5',
                  colorAxis: {
                    colors: ['#F5F5F5', '#455A64'],
                    minValue: 0,  
                    maxValue: 1,
                  }
                }
              }
            },
          },

          _onGoogleChartSelect: function(e) {
            var str = e.path[0].textContent.split('Select')[0].trim(),
                ar = this.items,
                i = ar.length;
            while(i---1){
              if(str === ar[i][0]){
                this.items[i][1]= ar[i][1] ? 0 : 1;
              }
            }
            this.$.geochart._dataTable=this.$.geochart._createDataTable(this.items);
            this.$.geochart._chartObject.draw( this.$.geochart._dataTable, this.$.geochart.options);
          },
        });
      })();
    </script>

  </dom-module>

  <x-element></x-element>

</body>
</html>

Upvotes: 0

Alon
Alon

Reputation: 2929

You have to add to the function _onGoogleChartSelect in the end after the while. it generate the data again and draw the chart.

this.$.geochart._dataTable=this.$.geochart._createDataTable(this.items);
this.$.geochart._chartObject.draw( this.$.geochart._dataTable, this.$.geochart.options);

and also you can use

  this.items[i]= ...

and not the

  // this  will fire event every time and I think that in this case you dont need it.
  this.set(...)

because you the google-chart ask for the data with ajax and so the data is not binding. so the solution is to insert the data into the functions that draw the chart.

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

Upvotes: 1

Related Questions