0
votes

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

2
Can you elaborate on what the events are and how they're fired? You may need to debounce them, or use async to make the stepNumber assignment wait for Polymer to finish what it's doing first. - Zikes
Zikes, this polymer element is like a workflow, every page is like a workflow step. The events are fired when the workflow step completes. For example, page-1 is a searching page. When the user clicks on search button, event1 is fired. Page-2 is a search result listing page. When one of the items in the list is clicked event2 is fired. Could you elaborate a little on async. ? - Jasmeet Singh
Just looked at the polymer code that's executing after the event method executes. It's basically the code that executes the event handler, followed by a "gesture recognition" code, where the value of "stepNumber" magically rolls back to 2 It's something like this - 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; r[type](ev); } } - Jasmeet Singh
added some more info. don't know if its useful - Jasmeet Singh

2 Answers

2
votes

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

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

0
votes

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);
    });
  }
});