21

I've got this situation where I'm trying to use the <template> tag in my html source:

<template id="some-id">
  <div id="content-container">
    <span>{{some_string}}</span>
  <div>
</template>

This ends up placing the template in the document but it is not considered to be in the DOM. This means that $("#content-container") is not found in browsers that support template tags. If I search for:

$("#some-id")

I get this back:

<template id=​"some-id">​
  #document-fragment
    <div id="content-container">
      <span>{{some_string}}</span>
    <div>
</template>​

None of this surprises me. What I need to know how to do is to clone the contents of the document-fragment and have a fresh node I can then stick into the DOM where I want it.

I have found examples of how to do this w/o jQuery but much of the code around this stuff is already using jQuery and I need to know how to use jQuery to do this.

My first thought was to get the html and then use it to create a new node:

stuff = $("#some-id").html()
new_node = $(stuff)

This results in the following errors:

Error: Syntax error, unrecognized expression: <the html string>

I don't know if the error is caused by the mustache syntax or not. I figure there has to be a jQuery solution to this behavior somewhere but when I search with Google I get craploads of hits for jQuery Templates, which are different.

Does anyone have thoughts, answers or pointers to sites/pages that will help me through this? I'm trying to avoid cobbling together something hackish.

EDIT: I ended up finding this solution (I'm still testing it to make sure it IS a solution but it looks promising);

template = $("#some-id")
content = template.html()
new_div = $("<div></div>")
new_div.html(content)

I end up with that containing div that I didn't really need previously but I can live with that. But this kind of feels kludgy. Does anyone have a better approach to this? The upside is that it will still work in browsers that haven't adapted the template tag behavior fully yet.

thanks!

Supersharp
  • 29,002
  • 9
  • 92
  • 134
jaydel
  • 14,389
  • 14
  • 62
  • 98
  • `$("#some-id").html` should be `$("#some-id").html()` – Nope Apr 10 '13 at 15:57
  • oops, yes that's a typo in my question. I'll fix it. – jaydel Apr 10 '13 at 15:58
  • Have a look at jquery .clone it sounds like it will help you ^^ http://api.jquery.com/clone/ – azzy81 Apr 10 '13 at 15:59
  • I tried that but it actually clones the content as the template. So the stuff I need inside is still just a #document-fragment and outside the conceptual DOM. I may have found an answer but I'm not sure how kludgy it is or if there's a better, kinder way to do it. I'll add it to my question in the hope that someone will be able to tell me if it's nasty or good. – jaydel Apr 10 '13 at 16:16
  • just FYI, - is not a valid character in id field although many software may support it, please consider using _. i saw my boss/partner old codes contains such mistakes, but really we should avoid it. – Hassan Faghihi Jun 12 '17 at 07:53
  • that's a reasonable assertion. The problem I faced at the time was that our dev team had a stylistic requirement that html ids use the dash and class names use the underscore. – jaydel Jun 14 '17 at 15:31
  • 1
    @deadManN Not sure where you learned that; according to the [HTML 4.01 specification](https://www.w3.org/TR/html401/types.html#h-6.2) from _1999_: "**ID** and **NAME** tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".")." They even use it in examples. HTML 5 removes even those restrictions and [simply says](https://www.w3.org/TR/html50/dom.html#the-id-attribute) an `id` "must contain at least one character [and] must not contain any space characters". – JuSTMOnIcAjUSTmONiCAJusTMoNICa Aug 11 '20 at 01:29

2 Answers2

22

Try:

var myTemplate = $("#some-id").html().trim();
var myTemplateClone = $(myTemplate);
HaNdTriX
  • 28,732
  • 11
  • 78
  • 85
9

I believe that this site will help explain how the shadow dom works and how templates interact with them. http://robdodson.me/blog/2013/08/27/shadow-dom-the-basics/

Furthermore it is actually very simple to clone a node of a shadow template and using jquery is not even needed.

Here is a jfiddle that demonstrates it: http://jsfiddle.net/dtracers/fhWc3/1/

HTML:

<div id = "hoster">
    <span class = "title">Title</span>
    <span class = "id">51ab89af</span>
</div>

<template id = "im-a-template">
    <h1><content select =".title"></content></h1>
    <h1>Class Id: <content select = ".id"></content></h1>
    <input type="text" placeholder = "Name"></input>  
</template>

Javascript:

// find where you want to put your shadow dom in
var host = document.querySelector('#hoster');

var root = host.createShadowRoot(); // create the host root

var template = document.querySelector('#im-a-template');

// this is the node of the object you wanted
var documentFragment = template.content;

// this is a cloned version of the object that you can use anywhere.
var templateClone = documentFragment.cloneNode(true);

root.appendChild(templateClone); // this empty root now has your template
dtracers
  • 1,534
  • 3
  • 17
  • 37
  • Be careful with using the 'content' tag, it was rejected from the HTML5 spec: http://stackoverflow.com/questions/17170547/is-there-a-content-tag-in-html-or-what-is-this-guy-teaching . – Nathan Weir Aug 07 '14 at 00:44
  • 2
    this is a different use of the content tag than explained there. http://www.html5rocks.com/en/tutorials/webcomponents/template/ The content tag is used to project information from outside the shadow root to data inside the shadow root – dtracers Aug 16 '14 at 19:54