Lit-element: Segregating html code from JS like polymer 1.0

Created on 20 Oct 2018  路  5Comments  路  Source: Polymer/lit-element

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?

Low Enhancement

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:

  • [ ] A way to iterate over a list, an object, or any iterable, including support for up-and-coming features such as for await...of, all inside the HTML template.
  • [ ] Conditional rendering (like Vue's v-if v-else-if and v-else).
  • [ ] Lifecycle events for conditional rendering that would allow for animation.
  • [ ] Perhaps a <transition> component like Vue's that would tie into said lifecycle events to make CSS animation easier.
  • [ ] Access to the class' variables and methods.
  • [ ] Most of all: All features that would be components should be either not included in the main package but can be imported or should be automatically included in the main package but automatically tree shaken when not used.

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).

All 5 comments

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:

  • [ ] A way to iterate over a list, an object, or any iterable, including support for up-and-coming features such as for await...of, all inside the HTML template.
  • [ ] Conditional rendering (like Vue's v-if v-else-if and v-else).
  • [ ] Lifecycle events for conditional rendering that would allow for animation.
  • [ ] Perhaps a <transition> component like Vue's that would tie into said lifecycle events to make CSS animation easier.
  • [ ] Access to the class' variables and methods.
  • [ ] Most of all: All features that would be components should be either not included in the main package but can be imported or should be automatically included in the main package but automatically tree shaken when not used.

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.

Was this page helpful?
0 / 5 - 0 ratings