I want to re-use my custom web component. My web pages are primarily defined by HTML files, not Javascript. Is there any viable way to insert my component into my main file using HTML/Javascript/jQuery? (I know I could assemble it via server-side programming, but that's far less reusable.)
Simple Example
File widget.html:
<template>
// some content
</template
Main file main.html:
<div id="foo"></div>
<script>
$("#foo").load("widget.html); // does not work.
</script>
Note that this code fails for only the <template> ... </template> portion of any file I try to load. If I place other valid (and even invalid) HTML elements such as <div> or <foobar>, those elements get inserted into my page.
Related
I don't think what I want is possible but I thought I would ask anyway!
Is there a way to grab stuff in the initial HTML file, modify it and then add it to the DOM before it has rendered?
For example I have an HTML file:
<body>
<div>Something here</div>
</body>
Is there a way I can intercept that <div> before it is added to the DOM as the HTML file is parsed.
I do not want to modify it after it has already been added to the page for clarity.
For another example, if I have an <img src="someimage.jpg"> is there a way to change that src attribute before the image gets added to the DOM so the request is never made.
Happy enough to use inline JS in the <head> (well I assume that is what I would have to do anyway if this is actually possible.)
I know once I have a service worker this all becomes arbitrary but I am working on the assumption of a cold cache and no external files (it is to optimise "above the fold" content primarily).
A cheap and simple way to prevent HTML from rendering is to wrap it in a <template>.
Templates will be parsed during page load like any normal HTML, but put in different documentFragments instead of being rendered, waiting to be manipulated, cloned or inserted anywhere you want when you are ready to render.
HTTP requests will not fire.
<template id="some_tpl">
<img src="someimage.jpg">
</template>
const template = document.getElementById('some_tpl');
const templateContent = template.content;
document.body.appendChild(templateContent);
I was going through some tutorials for vue.js front end framework when i came across <template>tag being used in html code at a lot of places:
<template v-for="(choice,index) in choices">
<h1>{{ choice }}</h1>
<p>{{ index }}</p>
</template>
I wanted to know what exactly is the purpose of this element. Is it something usually used in front end development?
The <template> element in general
The HTML Content Template (<template>) element is a mechanism for
holding client-side content that is not to be rendered when a page is
loaded but may subsequently be instantiated during runtime using
JavaScript.
Think of a template as a content fragment that is being stored for
subsequent use in the document. While the parser does process the
contents of the <template> element while loading the page, it does so
only to ensure that those contents are valid; the element's contents
are not rendered, however.
##The <template> element in Vue.js
You can find more information about it in the Vue.js guide. For example, in the context of v-if.
Conditionally render the element based on the truthy-ness of the expression value. The element and its contained directives / components are destroyed and re-constructed during toggles. If the element is a <template> element, its content will be extracted as the conditional block.
What that means exactly can be seen in this example:
<div v-if="true">Foo</div>
<template v-if="true">Bar</template>
which will result in:
<div>Foo</div>
Bar
The <template> element will not be part of the DOM after if has been processed by Vue.js anymore. The same applies when using the v-for directive on <template>.
See MDN:
The HTML Content Template (<template>) element is a mechanism for
holding client-side content that is not to be rendered when a page is
loaded but may subsequently be instantiated during runtime using
JavaScript.
Think of a template as a content fragment that is being stored for
subsequent use in the document. While the parser does process the
contents of the <template> element while loading the page, it does
so only to ensure that those contents are valid; the element's
contents are not rendered, however.
or the HTML specification:
The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.
In a rendering, the template element represents nothing.
I am trying to use mustache.js to deliver a multi-language version of my website. Therefore I am wondering if it is ok to add a <div id="mainContainer"> inside my <body> tag that contains all HTML elements of the page and then all mustache tags inside that big container via the usual:
var template = $('#mainContainer').html();
var html = Mustache.to_html(template, mustacheData);
$('#mainContainer').html(html);
It seems to work but I am wondering if there are pitfalls here (e.g. performance of reading, rendering and setting html of an entire page?). I have a dynamic bootstrap page with a couple of pages. The mustacheData would obtained the localized strings from a server in a specific language.
I am working on a project that requires two angularjs files, textAngular-sanitize and angular-sanitize. When both of these files are loaded in the header or footer, the part of the document that requires the file that is loaded first will work, however the element that requires the file that is loaded after the first ceases to work. I.e when angular-sanitize is loaded first, then the textAngular dependent element stops working, whereas if the textAangular file is loaded first, then the angular-sanitize element stops working. This is presumably because both files are loaded and run over the entire document. Is there a way to confine the 'scope' of one of the files to only one element on the page so that both scripts can be run without interfering with one another?
Or perhaps, is there an alternative method of loading external scripts other than the <script> tag?
Here is an example of what is going on:
<head ng-app="myApp">
<script src="scripts/textAngular.min.js"></script>
<script src="scripts/angular-sanitize.min.js"></script>
</head>
<body ng-controller="MainController" ng-init="initialize()">
<div id="ngSanitizeElement">
<!-- This element won't work -->
</div>
<div id="textAngularSanitizeElement">
<!-- This element will work -->
</div>
</body>
Not sure to understand your problem, but if you're looking for something to load external files from your controllers or your router, try ocLazyLoad : https://oclazyload.readme.io/docs
Which backend do you use? PHP? I would then put in the script tag the value of the right file depending?
Or can't you use 2 different ng-controllers?
<div ng-controller="textAngular ">
<div ng-controlelr="angular-sanitize">
I am using webcomponents.js to polyfill Firefox support of web components.
When loading an HTML template through an HTML import, a script within the template does not execute once the custom-element based on the template is added to the DOM of the main page.
It does execute when running the site in Chrome (which has native web components support).
However, both Firefox and Chrome execute such script when the template is placed within the main page itself.
See the example from Eric Bidelmann at HTML5Rocks. This runs both in Chrome and in Firefox (via webcomponents.js) - as long as the template is located in the same HTML file.
<!DOCTYPE html>
<html>
<body>
<button onclick="useIt()">Use me</button>
<div id="container"></div>
<script>
function useIt() {
var content = document.querySelector('template').content;
// Update something in the template DOM.
var span = content.querySelector('span');
span.textContent = parseInt(span.textContent) + 1;
document.querySelector('#container').appendChild(
document.importNode(content, true));
}
</script>
<template>
<div>Template used: <span>0</span></div>
<script>alert('Thanks!')</script>
</template>
</body>
</html>
But while the template text shows, it does NOT run when loading the template and its content via a HTML import link. As mentioned, it loads the content, but isn't executing the script in Firefox.
Is this a bug in webcomponents.js, or a bug in Firefox?
Anyone having a good idea for workarounds (other than "use Polymer or Angular")?
Note - this is based on using Firefox 43 and Chrome 47.
It is not a bug in Firefox, Internet Explorer 11 has the same behaviour (with webcomponents.js).
The importNode method is not polyfilled by webcomponents.js. That's why <script> elements are not activated when they are imported.
There an issue opened related to that problem.
My workaround: I don't insert scripts tags <script> inside an imported <template> (JS/HTML separated:).
Also, you could parse your <template> looking for <script> tags and try to activate/execute them manually (could be somewhat tricky...)
I did find a workaround for this issue which allows for script execution when the template element is activated.
This relies on the fact that HTML imports execute scripts located in the imported file immediately if they are not located inside a template tag.
So the solution is to just add one more HTML import inside the import file and load the script as external resource - this gets loaded once the template activates and executes right then and there.
So instead of having the below in the external import file:
<template>
<div>Template used: <span>0</span></div>
<script>alert('Thanks!')</script>
</template>
you have THIS:
<template>
<div>Template used: <span>0</span></div>
<link rel="import" href="script1.html">
</template>
and the referenced script1.html file contains the following:
<script>
alert('Thanks!')
</script>
Yes, it's one more HTTP request, but it's workable and simple.
This solves any script which must run upon initialization of a template element. Script needed for later activation can be materialized in terms of function definitions, or inline scripts.
Note:
Another workaround is to add a "div" tag in the external import file below (and outside) the template section with an id="script1" and then use some JS to extract the div's content and add a script tag instead into the template. Since you anyway need JS to activate the template it's not much of a change,but this feels more like a hack.