Daniel Robert Miller
Daniel Robert Miller

Reputation: 109

Polymer Binds when Data sent One Way

I am currently using Polymer on a project and for some reason I am getting data binding when I do not expect nor want it.

What I currently have is a boilerplate Polymer project that is supposed to have the new element I created (named shokka-eval-chart). This is working great but somehow information is being shared between the three elements.

In order to debug this problem I added in console.log messages that would tell me what was going on. Each time the console logs come back it indicates that the userData has been modified. Where is this modification happening and why?

Some things that you may notice:

  1. User Data is sent in using one way data binding::: [[userInfo.evaluations]]
  2. Index should not be notified of my changes to User Data::: notify: false

Some places that I can think of that I may have an issue:

  1. HTML - I may not be passing things into the tag correctly.
  2. Javascript - I have no idea how but I may be modifying the userData from there.
  3. Polymer - The obvious location to look. I probably am misunderstanding one of the concepts.

Please let me know where this is happening and what I am doing wrong to have this happen. Thanks in advance.

CONSOLE LOGS

shokka-eval-chart.html:89 Jan 16
shokka-eval-chart.html:91 40
shokka-eval-chart.html:92 40
shokka-eval-chart.html:93 0
shokka-eval-chart.html:89 Jan 16
shokka-eval-chart.html:91 0
shokka-eval-chart.html:92 40
shokka-eval-chart.html:93 -40
shokka-eval-chart.html:89 Jan 16
shokka-eval-chart.html:91 -40
shokka-eval-chart.html:92 40
shokka-eval-chart.html:93 -80

INDEX

<body unresolved class="fullbleed layout vertical">
 <span id="browser-sync-binding"></span>
  <template is="dom-bind" id="app">
   <paper-drawer-panel id="paperDrawerPanel">
    <paper-scroll-header-panel main condenses keep-condensed-header>
     <div class="content">
      <iron-pages attr-for-selected="data-route" selected="{{route}}">
       <section data-route="home">
        <paper-material elevation="1">
         <shokka-eval-chart id="comparison1" 
                            user-evaluations="[[userInfo.evaluations]]" 
                            eval-ref="{{baseRef}}/evalResults">
         </shokka-eval-chart>
        </paper-material>
        <paper-material elevation="1">
         <shokka-eval-chart id="comparison2" 
                            user-evaluations="[[userInfo.evaluations]]" 
                            eval-ref="{{baseRef}}/evalResults">
         </shokka-eval-chart>
        </paper-material>
        <paper-material elevation="1">
         <shokka-eval-chart id="comparison3" 
                            user-evaluations="[[userInfo.evaluations]]" 
                            eval-ref="{{baseRef}}/evalResults">
         </shokka-eval-chart>
        </paper-material>
       </section>
      </iron-pages>
     </div>
    </paper-scroll-header-panel>
   ...

Component Code

<link rel="import" href="../../bower_components/polymer/polymer.html">

<dom-module id="shokka-eval-chart">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>
    <google-chart id="{{id}}" 
              type="{{type}}" 
              options='{{options}}'
              data='[[data]]'>
    </google-chart>
  </template>
  <script>
  (function() {
    'use strict';

    Polymer({
      is: 'shokka-eval-chart',

      properties: {
        id: {
          type: String
        },
        userEvaluations: {
          type: String
        },
        evalRef: {
          type: String
        },
        userData: {
          type: Array,
          value: [ ["Date", "Professionalism", "Skills", "Work Completion" ],
                   ["Jan 16", 40, 35, 37 ],
                   ["Feb 16", 39, 35, 34 ],
                   ["Mar 16", 38, 36, 39 ],
                   ["Apr 16", 42, 38, 40 ],
                   ["May 16", 42, 37, 41 ],
                   ["Jun 16", 43, 38, 40 ],
                   ["Jul 16", 44, 40, 41 ],
                   ["Aug 16", 45, 43, 42 ],
                   ["Sep 16", 46, 46, 41 ],
                   ["Oct 16", 45, 44, 42 ] ],
          notify: false
        },
        data: {
          type: Array,
          computed: 'computeData(avgData, userData)',
          notify: false
        },
        options: {
          type: Object,
          value: { "title": "Evaluation Comparison" }
        },
        type: {
          type: String,
          value: "column"
        },
        avgData: {
          type: Array,
          value: [ ["Date", "Professionalism", "Skills", "Work Completion" ],
                             ["Jan 16", 40, 40, 40 ],
                             ["Feb 16", 40, 40, 40 ],
                             ["Mar 16", 40, 40, 40 ],
                             ["Apr 16", 40, 40, 40 ],
                             ["May 16", 40, 40, 40 ],
                             ["Jun 16", 40, 40, 40 ],
                             ["Jul 16", 40, 40, 40 ],
                             ["Aug 16", 40, 40, 40 ],
                             ["Sep 16", 40, 40, 40 ],
                             ["Oct 16", 40, 40, 40 ] ],
          notify: false
        }
      },

      computeData: function(avgData, userData){
        console.log(userData[1][0])
        var data = userData.slice();
        console.log(userData[1][1])
        console.log(avgData[1][1])
        console.log(userData[1][1]-avgData[1][1])
        data[1][1] = userData[1][1] - avgData[1][1]
        return data;
      }
  });
  })();
  </script>
</dom-module>

UPDATE: Per Günter Zöchbauer's suggestion I have changed var data = userData; to var data = userData.slice();. However this has not yet solved the issue. There seems to be something else that I am missing here.

UPDATE: After looking at the userData after data was modified it appears that it was still pointing to the same object. I changed var data = userData.slice(); to

    var data = [];
    for (var i = 0, len = userData.length; i < len; i++) {
      data[i] = userData[i].slice();
    }

in order to solve this issue. This has solved the issue I was encountering but still leads me to wonder why userData was being modified from a different tag. If someone could comment and let me know why it would be very appreciated.

Upvotes: 2

Views: 141

Answers (2)

Rickard Elim&#228;&#228;
Rickard Elim&#228;&#228;

Reputation: 7591

This could possibly be it, but I can't remember that it worked when I tried it myself. My emphasis in italics below.

Configuring default property values

Default values for properties may be specified in the properties object using the value field. The value may either be a primitive value, or a function that returns a value.

If you provide a function, Polymer calls the function once per element instance.

When initializing a property to an object or array value, use a function to ensure that each element gets its own copy of the value, rather than having an object or array shared across all instances of the element.

  data: {
    type: Object,
    value: function() { return {}; }
  }

Source: https://www.polymer-project.org/1.0/docs/devguide/properties#configure-values

Upvotes: 1

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657058

I have the suspicion you expect this line

var data = userData;

to create a copy of userData but after this line, data and userData point to the same data structure.

Try instead

var data = userData.splice();

Just a guess. If this isn't the issue I don't know what causes the problem.

Upvotes: 2

Related Questions