Jasmeet Singh
Jasmeet Singh

Reputation: 2538

Polymer bounded property not updating (sometimes)

This problem is with 1.0

I have the following html in a polymer element

  <iron-selector attr-for-selected="step-number" selected="{{stepNumber}}">
    <section step-number="1">
      <page-1 id="page1"></page-1>
    </section>
    <section step-number="2">
      <page-2 id="page2"></page-2>
    </section>
    <section step-number="3">
      <page-3 id="page3"></page-3>
    </section>`

page 1 fires an event - event1, page-2 fires event2. Here's my javascript for the polymer element

function () {
  Polymer({
    is: 'name',
    ready: function() {
      this.stepNumber = 1;
      var firstStep = this.$.page1;
      var secondStep = this.$.page2;
      var thirdStep = this.$.page3;
      var that = this;
      firstStep.addEventListener('event1', function(e) {
        that.stepNumber = 2;                       // WORKING
      });
      secondStep.addEventListener('event2', function(e) {
        that.stepNumber = 3;                      // NOT WORKING
      });
    }
  });

Here's the interesting part: Both events get fired, the value for stepNumber gets updated inside event1 handler but not inside event2 handler. I also debugged this and inside the event2 handler the value of stepNumber DOES get updated (page-3 element gets the tag "iron-selected") but it doesn't persist. After a bunch of polymer code executes the value is back to 2.

Looks like a bug in polymer?

Some info from the debugger -

polymer code that's executing after the event method is basically the code that executes the event handler, followed by a "gesture recognition" code (which i guess is the on-click), where the tag iron-selector is added to page-2 section

var recognizers = Gestures.recognizers;

for (var i = 0, r; i < recognizers.length; i++) 
{ 
   r = recognizers[i]; 
   if (gs[r.name] && !handled[r.name]) {
     handled[r.name] = true; // in here for r.name = "tap"
   r[type](ev); // type = click. ev = MouseEvent. ev.target = iron-selector
} 
}

Digging deeper - this creates an event handler

_createEventHandler: function(node, eventName, methodName) {
var host = this;
return function(e) {
if (host[methodName]) {
hostmethodName;
} else {
host._warn(host._logf("_createEventHandler", "listener method " + methodName + " not defined"));
}
};

host is iron-selector. methodName is _activateHandler where _itemActivate is called for section of page-2

_activateHandler: function(e) {
      // TODO: remove this when https://github.com/Polymer/polymer/issues/1639 is fixed so we
      // can just remove the old event listener.
      if (e.type !== this.activateEvent) {
        return;
      }
      var t = e.target;
      var items = this.items;
      while (t && t != this) {
        var i = items.indexOf(t);
        if (i >= 0) {
          var value = this._indexToValue(i);
          this._itemActivate(value, t);
          return;
        }
        t = t.parentNode;
      }
    },
_itemActivate: function(value, item) {
      if (!this.fire('iron-activate',
          {selected: value, item: item}, {cancelable: true}).defaultPrevented) {
        this.select(value);
      }

_itemActivate is where the value of stepNumber changes to 2

Upvotes: 0

Views: 605

Answers (2)

Scott Miles
Scott Miles

Reputation: 11027

Clear the activateEvent property (activate-event attribute) of the iron-selector, like this:

<iron-selector attr-for-selected="step-number" selected="{{stepNumber}}" activate-event="">

Upvotes: 2

Zikes
Zikes

Reputation: 5886

Try this:

Polymer({
  is: 'name',
  ready: function() {
    this.stepNumber = 1;
    var firstStep = this.$.page1;
    var secondStep = this.$.page2;
    var thirdStep = this.$.page3;
    var that = this;
    firstStep.addEventListener('event1', function(e) {
      that.async(function(){
        that.stepNumber = 2;
      },0);
    });
    secondStep.addEventListener('event2', function(e) {
      that.async(function(){
        that.stepNumber = 3;
      },0);
    });
  }
});

Upvotes: 0

Related Questions