Accessing member functions in Polymer elements

Polymer logoUpdate:

Rob Dodson clarified a lot of my confusion with his comment below. I’ve made changes to the post to reflect his information. Thanks again for the help!

Here’s the source code for my this project, and a tutorial will follow.

I’m working on a silly Polymer project right now, which parses a Pokemon database and returns a picture of a Pokemon, then speaks the creature’s name over your speakers.

It’s my first time using Polymer, and I’m certainly getting snagged in a few spots. Most recently, it was trying to return member functions of a Polymer object that I created. Took me forever to figure this out.

The wrong way

I have a Web Component which looks like:

<x-radial-buttons id="radial-button-template"></x-radial-buttons>

If I try to access it by its ID….

var  temp = document.querySelector("#radial-button-template");
// returns <x-radial-buttons id=”radial-button-template”></x-radial-buttons>

But I cannot access any of the function it. They return “undefined”.  So if I tried to do

var  temp = document.querySelector("#radial-button-template");
temp.getFirstElement  // returns undefined

Why is this happening?

The reason behind this is due to the Shadow DOM’s encapsulation. It is both a gift and a curse. In this case, I am accessing the element, and not the shadowRoot, which will expose the public methods attached to the Shadow DOM object.

In the next step, you will see how I can access the member functions in my custom element, as well as how I can reutrn nodes that lie even deeper in my web component.

Rob Dobson of Google’s Polymer team explains this well in his blog post. Eric Bidleman goes into even more detail in his advanced Shadow DOM article. I highly suggest taking the time to read these over, to have a better comprehension of how this verison of the DOM works.
 

One way of doing it….

var btn = document.querySelector("x-radial-buttons");

Notice that I’m not using the hash symbol (#) to access the element, as though it were an ID. Instead, you need to simply refer to the name of the polymer-element itself:

document.querySelector("x-radial-buttons");

so now I can write:

var temp = document.querySelector("x-radial-buttons");
// ALSO returns <x-radial-buttons id="radial-button-template"></x-radial-buttons>

Now I can access all of the members:

var temp = document.querySelector("x-radial-buttons");
temp.getFirstElement
// returns <paper-radio-button label="English-US" id="paper_radio_btn_en-US" on-click="{{ changeAccentUS }}" role="radio" tabindex="0" aria-checked="false" aria-label="English-US"></paper-radio-button>

Therefore, I suggest not assigning an ID to your polymer-element at all. As Rob made clear in the comments below, you can query for a custom element however you want (via ID, class, attr, or element name) and get the same thing. Here’s his example: http://jsbin.com/qikaya/2/edit

Another way of doing it…

You can also grab the ID of a polymer element and access the member functions.

This is done by ‘polymer-ready’ event. As the docs describe it:

Polymer parses element definitions and handles their upgrade asynchronously. If you prematurely fetch the element from the DOM before it has a chance to upgrade, you’ll be working with a plain HTMLElement, instead of your custom element.

And this is exactly the issue I was running into earlier. I was trying to grab functions within my polymer-element before polymer had a chance to upgrade it.  Here’s an example:
 

In conclusion, as long as you wrap the functions you are trying to call in the polymer-ready event, you should be good to go, and can call functions from your polymer-element.

Here is how I am using it

-----------------------


subscribe-to-youtube

Leave a Reply