4
votes

I'm trying to inject and display a <template> the right way into a Polymer Webapp, but I have a few difficulties with it. (… or maybe I misunderstood the 1.0 Documentation?)

The documentation about manipulation the DOM says:

Polymer provides a custom API for manipulating DOM such that local DOM and light DOM trees are properly maintained. These methods and properties have the same signatures as their standard DOM equivalents, except that properties and methods that return a list of nodes return an Array, not a NodeList.

Note: All DOM manipulation must use this API, as opposed to DOM API directly on nodes.

So I guess I have to use Polymer.dom API everywhere to manipulate the DOM, which makes sense to me, because this way Polymer can stay in sync with the generated shady DOM. No DOM.appendChild(), instead Polymer.dom().appendChild(). And manipulating the shady DOM directly wouldn't be a great idea … or would it?

Imagine a simple page structure:

<body>
  <template is="dom-bind" id="app">
    <main>
      <template is="dom-bind" id="content">
        <p>Lorem ipsum dolor sit amet.</p>
      </template>
    </main>
  </template>
</body>

And a second small snippet which I can import into the page.

<template id="snippet">
  <p>Consectetur adipisici elit.</p>
</template>

This template should be replaced/referenced with the #content. So, let's start.

Importing the snippet is easy. I can fetch it and get the DOM Element of it.

Polymer.Base.importHref('/snippet', function(e) {
  // on success: imported content is in e.target.import

  var template = Polymer.dom(e.target.import).querySelector('#snippet');
  // until here it works, `template` is the template from my snippet
  ...

Now I guess I have to append this to my template#app and change the ref of template#content to content… if changing the ref is still supported? And how am I supposed to do that? I get stuck every time, no matter how I approach this.

var app = Polymer.dom(this).querySelector('#app'); // Works, is template#app
var app = document.querySelector('#app'); // Same result

Polymer.dom(app).appendChild(template); // will append it, but outside of the document fragment
Polymer.dom(app.root).appendChild(template); // won't do anything

Polymer.dom(app).querySelector('template'); // undefined
Polymer.dom(app.root).querySelector('template'); // undefined
app.querySelector('template'); // undefined

I looked hours and days into this, trying to find a solution. It works with the standard DOM API, but I don't think that's the right way to do this. If somebody could solve my confusion, it would be really great.

EDIT: Or will Polymer.dom(this) do it's thing and I don't need to call Polymer.dom(app)? But again, I tried it and it won't work. Aaargh, it's just so confusing.

1
What exactly is your use case? Is there any reason why your #snippet can't be of a <div> tag for example? BTW, I don't think there is a direct replacement for ref in Polymer 1.0 currently. Also, if you are trying to imperatively insert a data-bound template into DOM, you might be out of luck because it is not supported per github.com/Polymer/polymer/issues/1778. - zerodevx
I've seen this procedure in the Google I/O Webapp and it just seems to be so clean. You just append a template at the end of your document and reference it somewhere else – boom, it's displayed. But the I/O Webapp uses v0.8 (or even v0.5?). It's a bummer this isn't supported anymore. - Timo Mämecke
I think my problem/confusion is that the new shady DOM puts the Webcomponents outside of the Shadow DOM and I don't know where and how to manipulate it. For me it would be logical to manipulate the original DOM and Polymer keeps the shady DOM in sync with it. But using Polymer.dom() I'll end up manipulating the shady DOM, which feels so dirty. - Timo Mämecke
See here. Seems like template ref support can't be added until the base API can be updated to support dynamic addition of bindings at instance time. So, I imagine that has something to do with why this is fairly difficult. - Ben Davis
My use case is to inject a custom template from outside into a complex iterating custom element. I think that's quite common ? Think of an element doing a db query and renders it. I'd like to customize formatting .. do I miss something ? - R.Moeller

1 Answers

2
votes

If I understood you correctly and you want to insert the template to local dom (inserting it somewhere else doesn't really make sense) then it's Polymer.dom(this.root).appendChild.

From https://www.polymer-project.org/1.0/docs/devguide/local-dom.html#dom-api: In order to insert/append into the local dom of a custom element, use this.root as the parent.