I may have overlooked but is there a way to keep different files for html and js code like it was possible in polymer 1.x?
There are a couple of ways you could do this, the easiest would most likely be to make to .js files like so:
// This is your "html" file (foo-x-html.js)
import { html } from '@polymer/lit-element'
// Cannot be arrow function, that would cause it to bind to this context instead of the class' context
export default function() {
return html`
<p>My name is ${this.name}</p>
`
}
// This is the main component file (foo-x.js)
import { LitElement } from '@polymer/lit-element'
import template from './foo-x-html.js'
class FooX extends LitElement {
render() {
return template()
}
}
...
Essentially this way of doing it is outsourcing the render method to another file. The only problem is that it could get confusing to switch back and forth between these files to check what you put on your class.
Another option would be to have your js file read an html file as a string and run eval on it with html`` wrapped around it, but that way just seems all around hacky and bad.
The above recommendation is a good way to segregate your template from the rest of your element code; however, the template itself will still be a template literal and not HTML.
As a future enhancement to lit-html, it should be possible to convert HTML into a template literal that lit-html can understand.
A quick note: I wanted to keep my HTML and JS separate, too, so I made rollup-plugin-bundle-lit-html.
If you use Rollup, you can import a template function from your HTML like:
import { template } from "./my.html";
template( { someVar } );
The plugin essentially does what @ChrisBrownie55 mentions above: it creates a Function wrapper that returns a template function with your HTML inside it.
The main problem I've run into is that in order to use lit-element, you must use the html that lit-element exports. I've worked around this problem by allowing you to pass in your own html as the second parameter to the template function.
import { html } from "lit-element";
import { template } from "./my.html";
template( { someVar }, html );
Hopefully this helps some people who like to keep their HTML separate from their JS.
@rockerest I like your solution but that doesn't solve the underlying problem, in my opinion. I think the issue here is that we are trying to segregate the _Template_ from the _JavaScript_ which are very closely coupled. So much so, that you have to pass variables to this template from the render function. In the end, the template isn't necessarily separated from the JavaScript, but instead, it is separated from the render's setup. Personally, I don't think that it makes sense to separate the variables you need to use in the template, from the template itself.
I feel that introducing separate HTML template files without a major change to LitElement that makes it more like Vue's single file components or Angular's many file components will serve no purpose, as LitElement's current APIs are more akin to that of React's. Which seems like what the web standard is going to be like going forward, at least in the sense that React and LitElement both have their render method coupled to their template.
If LitElement's syntax was going to be more like Vue/Angular's uncoupled syntax, here are the things I'd think that it would need to have going forward:
for await...of, all inside the HTML template.v-if v-else-if and v-else).<transition> component like Vue's that would tie into said lifecycle events to make CSS animation easier.There's probably more to add here but that's what I could come up with.
Overall, I believe that the future of webcomponents is the coupling of the JavaScript and HTML Template, as it provides extensive functionality with built-in features (i.e. the list above).
lit-html is inherently JavaScript, so there's no way to do this. You can use UpdateElement and a different template system.
Most helpful comment
@rockerest I like your solution but that doesn't solve the underlying problem, in my opinion. I think the issue here is that we are trying to segregate the _Template_ from the _JavaScript_ which are very closely coupled. So much so, that you have to pass variables to this template from the render function. In the end, the template isn't necessarily separated from the JavaScript, but instead, it is separated from the render's setup. Personally, I don't think that it makes sense to separate the variables you need to use in the template, from the template itself.
I feel that introducing separate HTML template files without a major change to LitElement that makes it more like Vue's single file components or Angular's many file components will serve no purpose, as LitElement's current APIs are more akin to that of React's. Which seems like what the web standard is going to be like going forward, at least in the sense that React and LitElement both have their render method coupled to their template.
If LitElement's syntax was going to be more like Vue/Angular's uncoupled syntax, here are the things I'd think that it would need to have going forward:
for await...of, all inside the HTML template.v-ifv-else-ifandv-else).<transition>component like Vue's that would tie into said lifecycle events to make CSS animation easier.There's probably more to add here but that's what I could come up with.
Overall, I believe that the future of webcomponents is the coupling of the JavaScript and HTML Template, as it provides extensive functionality with built-in features (i.e. the list above).