Oscar Jiménez
Oscar Jiménez

Reputation: 13

polymer 1.0 event firing among nested components

I have a problem in Polymer 1.0 related to event propagation within a nested structure of web components. In particular, I am trying to dynamically configure a web component named wc-split by means of a collection of other components named wc-split-rule located within its local DOM. The following snippet of code shows a correct form of use:

<wc-split-test>
    <wc-split>
        <wc-split-rule key="{{k1}}" ...></wc-split-rule>
        <wc-split-rule key="{{k2}}" ...></wc-split-rule>
        <wc-split-rule key="{{k3}}" ...></wc-split-rule>
   </wc-split> 
</wc-split-test>

As it can be seen in the previous example, the aim is to provide to the wc-split component the values on key attributes within each wc-split-rule component. As we need dynamic reconfiguration capabilities, the architectural strategy starts by firing an event each time a change in key attributes is met and those changes are promoted by bubbling up to reach the wc-split component, which process them.

The followed approach works properly when [1] it is both tested in a pure HTML context with literal values and [2] within a component template with data-bound values. Nevertheless, [3] when it is tested within a component template using literal values, changes are not promoted. It seems that event propagation are ignored or listener defined in wc-split does not catch the event:

<wc-split-test>
    <wc-split> <!-- does not work -->
        <wc-split-rule key="k1" ...></wc-split-rule>
        <wc-split-rule key="k2" ...></wc-split-rule>
        <wc-split-rule key="k3" ...></wc-split-rule>
    </wc-split>
</wc-split-test>

The following listing shows implementation of both components [https://goo.gl/OkU9jQ]:

    <dom-module id="wc-split-rule">
        <script>                
            Polymer({
                is: 'wc-split-rule',  

                properties: {
                    key  : {
                        type: String,
                        reflectToAttribute: true,
                        notify: true,
                        value: '',
                        observer: '_changed'
                    },
                }, 

                _changed: function (){
                    this.fire('wc-split-rule', {
                        key     : this.key,
                    });                        
                }    

            });
        </script>
    </dom-module>


    <dom-module id="wc-split">   
        <template>
           <content></content>         
        </template>

        <script>     
            Polymer( { 
                is: 'wc-split', 

                listeners: {
                    'wc-split-rule': 'onRule'
                },

                ready: function(){
                   ...
                },

                onRule: function (event, context){
                    ... // this is executed in test [1] and [2] NOT in [3]                        
                }
            });     
        </script>

    </dom-module>


    <dom-module id="wc-split-test">          
        <template>              
            <wc-split id="split">
                <wc-split-rule key="e1"/>                        
            </wc-split>            
        </template>

        <script>     
            ...
        </script>

    </dom-module>

Surprisingly, the same code on Polymer 0.5 works properly for each test scenario [https://goo.gl/CHV3JE]:

    <polymer-element name="wc-split-rule">  
        <script>

            Polymer('wc-split-rule', {
                publish : {
                    key     : '',                       
                },

                observe: {
                    key     : '_changed',                       
                },

                _changed: function (){
                    this.fire('wc-split-rule', {
                        key     : this.key,
                    });                        
                }    

            });
        </script>
    </polymer-element>


    <polymer-element name="wc-split">
        <template>
            <div on-wc-split-rule="{{onRule}}">
                <content select="wc-split-rule"></content>
            </div>
            <content></content>        
        </template>
        <script>

            Polymer('wc-split', {                    

                ready: function(){
                    ...
                },                   

                onRule: function (event, context){
                    ... // this is always executed
                }
            });     
        </script>

    </polymer-element>


     <polymer-element name="wc-split-test">
        <template>              
            <wc-split id="split">
                <wc-split-rule key="e1"/>                        
            </wc-split>            
        </template>

        <script>
            ...
        </script>

    </polymer-element>       

Upvotes: 1

Views: 1125

Answers (1)

ebidel
ebidel

Reputation: 24119

This boils down to a timing issue. The wc-split-rule event is firing before your wc-split element is registered. Therefore, the event is being missed. It's only an issue when the elements are first booted up b/c you have a parent element that's also a custom element. One way around this is to ensure the event fires after the wc-split-rule is attached:

attached: function() {
  this._changed();
},

This works: http://jsbin.com/yixinuhahu/edit?html,output

Upvotes: 1

Related Questions