The reason this didn't work inside the lifecycle callback without setTimeout or this.async is that right after attaching your element the dom-if template has not yet rendered. Upon attaching your element, Polymer calls the attached callback. However, when the value gets set on the the dom-if, an observer runs and debounces its own _render function. The debounce waits an amount of time to catch any other calls to it, and then it executes the ._render function and attaches the element to the DOM. In other words, when the attached callback runs, normally the dom-if template hasn't rendered yet.
The reason for this debounce is performance. If several changes were made within a very short span of time, this debounce prevents the template from rendering several times when the result we would care about is the end result.
Fortunately, dom-if provides a .render() method which allows you to make it render synchronously. All you need to do is add an id to your dom-if, switch to an attached callback and call like this:
<template>
<template id="someDomIf" is="dom-if" if="[[condition]]" restamp>
<span id="myspan"></span>
</template>
</template>
attached() {
this.$.someDomIf.render();
var c = document.getElementById("myspan"); //<------- should be defined
var d = this.$$("#myspan"); //<------- should be defined
}
Triggering a synchronous render on the dom-if shouldn't be a huge performance problem, since luckily your element should only be getting attached once.
Edit: As it turns it, this even works in a ready callback:
<template>
<template id="someDomIf" is="dom-if" if="[[condition]]" restamp>
<span id="myspan"></span>
</template>
</template>
ready() {
this.$.someDomIf.render();
var c = document.getElementById("myspan"); //<------- should be defined
var d = this.$$("#myspan"); //<------- should be defined
}
See this fork of your plunker:
http://plnkr.co/edit/u3richtnt4COpEfx1CSN?p=preview
condition
istrue
, whencondition
isfalse
none will work. – Philpsdom-if
. This worksthis.async(function () {console.log('this.$$("#myspan")',this.$$("#myspan"));});
(same as in Flavio Ochoa's answer). – Philps