Search code examples
polymer-1.0dom-eventsidioms

How can component in iron-pages know when it is selected


I have a Polymer 1.0 iron-pages element containing two custom elements:

<iron-pages selected="...">
  <my-page>A</my-page>
  <my-page>B</my-page>
</iron-pages>

I would like to take some action, like fetching ajax content, in my-page component, when the page becomes selected. How can I do this?

I came up with some ideas:

  1. create a third component containing the iron-pages and wiring the events

    <dom-module id="my-controller">
      <template>
        <iron-pages selected="..." on-selected-changed="onPageChanged">
      ...
      <script>Polymer({...
        ...
        onPageChanged:function(){
          var page = ...;
          page.selected = true;
        }
    

    and

    <dom-module id="my-page">
      ...
      onSelected:function(){
        // fetch data
      }
    

    seems being rather much of an overhead to me, is this really necessary?

  2. use <iron-pages selectedAttribute="..." ...>

    but I could not find a way to detect the attribute change in <my-page>

Are there common patterns to solve this?


Solution

  • My solution was similar to your option A, but using events instead of method calls - its a more correct approach, and I'm actually baffled why Polymer's ironSelectableBehavior didn't implement it directly:

    <iron-pages id="pages" ...>
       <my-first-page></my-first-page>
       <my-second-page></my-second-page>
    </iron-pages>
    
    ...
    
    <script>
    Polymer({
        is: 'my-app',
        listeners: {
            'pages.iron-select': 'pageSelected',
            'pages.iron-deselect': 'pageDeselected'
        },
        pageSelected: function(e) { e.detail.item.fire('iron-select'); },
        pageDeselected: function(e) { e.detail.item.fire('iron-deselect'); })
    });
    </script>
    

    Then, in your element, listen for these events:

    Polymer({
        is: 'my-custom-element',
        listeners: {
            'iron-select': '_refreshData'
        },
        _refreshData: function(e) {
            // load some data
        }
    });
    

    Option B should also work - you probably need to set up the correct property and put an observer on it. In your component that contains iron-pages set up the attribute using the hyphenated form:

    <iron-pages selected-attribute="activated" ...>
       <my-first-page></my-first-page>
       <my-second-page></my-second-page>
    </iron-pages>
    

    Then in your custom component set up the property and the observer:

    Polymer({
        is: 'my-first-page',
        properties: {
            activated: {
                type: Boolean,
                observer: '_activationChanged'
            }
        },
        _activationChanged: function(newval, oldval) {
            if (newval) // == true
                console.log("just activated");
        }
    });