Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get polymer parent element

So I've been using Polymer for about a day now and I'm having trouble phrasing this question, so if my approach is way off base, please don't feel the need to fix this, rather point me in the right direction.

What I have are custom elements within custom elements and I would like a child element to affect the parent's attributes. The approach I'm taking is to create a click handler, closing the parent element in an IIFE, then passing that handler to the sub component. Like so...

Polymer({
  ready: function(){
     this.superHandler = (function(p) {
        return function() {
          // "this" here will be the sub-component
          p.title = this.title;
        }
     })(this);
  }
});

Where the parent element uses it in it's template like...

<polymer-element name="parent-element">
  <template>
    <sub-element on-click={{superHandler}} />
  </template>
</polymer-element>

This (in my real code, though it's possible there's typos here) works in everything but IE, and I know IE isn't officially supported, but it's so close I don't want to give up on it. Things I want to avoid are repeated references to parentNodes and shadowRoots to get to the parent I'm looking for.

Edit

I forgot to mention how it's failing in IE, and why I want to avoid the parentNode call. In IE, when it goes to dispatch the event specifically line 9131 of polymer.js, the variable "method" and the reference in obj[method] are strings in IE, and so have no method apply. The reason I want to avoid the parentNode is because the caller isn't the direct parent, so I don't want to keep getting parentNodes until I find the right one, since the code is much more understandable when I can name the variable.

Edit 2

What I'm going with now (since it's working in IE9), though I'm leaving the question open for a better answer is to continue with the IIFE, returning a function that takes an argument that is the child. Then the child will find the parent of interest by a querySelector. This means the child has to have fore-knowledge of the parent and the method to call, which isn't ideal, but... IE.

So the parent sets it up as...

Polymer('parent-element', {
  ready: function(){
     this.superHandler = (function(p) {
        return function(child) {
          p.title = chile.title;
        }
     })(this);
  }
});

And the child must get it by a query selector, say by 'parent-element' and know the name 'superHandler' (not the actual name)

Polymer('child-element',{
        clickHandler: function(){
            var p = document.querySelector('parent-element').superHandler;
            p(this);
        }
    });

Better ideas?

like image 489
Felix Avatar asked Mar 11 '15 04:03

Felix


3 Answers

You can use own events to pass data between elements.

Parent component:

<polymer-element name="parent-element">
  <template>
    <!-- ... -->
    <sub-element></sub-element>
  </template>
  <script>
  Polymer({
    ready: function() {
      this.addEventListener('eventFromChild', this.myAction);
    },
    myAction: function(event) {
      console.log(event.detail);
    },
  });
  </script>

Child component:

<polymer-element name="sub-element" attributes="foo bar">
  <template>
    <!-- ... -->
    <button on-click="{{passParams}}">Send</button>
  </template>
  <script>
  Polymer({
    ready: function() {
      this.foo = 'abc';
      this.bar = '123';
    },
    passParams: function() {
      this.fire('eventFromChild', { foo: this.foo, bar: this.bar });
    },
  });
</script>
like image 153
Max Zuber Avatar answered Nov 12 '22 09:11

Max Zuber


Here is a simple way to get access to the parent element in Javascript. This works in a personal work (polymer 0.5 - as mentioned in the comments, things are different in 1.0). Not tested on IE, but it seems to me a simple solution:

Polymer('sub-element', {
  ready: function(){
     this.parentNode;
  }
});
like image 42
bdulac Avatar answered Nov 12 '22 10:11

bdulac


Thanks for the custom event suggestions. That got me to go back and look at the core elements again to find this.

Then I just need to add a

<core-signals on-core-signal-my-event="{{myEventHandler}}"></core-signals>

Fire off a "core-signal" event with a name of (in this example) "my-event" and create a method "myEventHandler" on the parent e.g.

Polymer({
  myEventHandler: function(e,detail,sender) {...}
})
like image 1
Felix Avatar answered Nov 12 '22 08:11

Felix