Code Monkey home page Code Monkey logo

lit-element's Introduction

Lit

Simple. Fast. Web Components.

Build Status Published on npm Join our Discord Mentioned in Awesome Lit

Lit is a simple library for building fast, lightweight web components.

At Lit's core is a boilerplate-killing component base class that provides reactive state, scoped styles, and a declarative template system that's tiny, fast and expressive.

Documentation

See the full documentation for Lit at lit.dev.

Additional documentation for developers looking to contribute or understand more about the project can be found in dev-docs.

npm

To install from npm:

npm i lit

Lit Monorepo

This is the monorepo for Lit packages.

lit 2.x source is available on the 2.x branch. lit-html 1.x source is available on the lit-html-1.x branch.

Packages

Contributing to Lit

Lit is open source and we appreciate issue reports and pull requests. See CONTRIBUTING.md for more information.

Setting up the lit monorepo for development

Initialize repo:

git clone https://github.com/lit/lit.git
cd lit
npm ci

Build all packages:

npm run build

Test all packages:

npm run test

Run benchmarks for all packages:

npm run benchmarks

See individual package READMEs for details on developing for a specific package.

lit-element's People

Contributors

abdonrd avatar abraham avatar aomarks avatar bicknellr avatar christian24 avatar dakmor avatar danielbarion avatar dependabot[bot] avatar dfreedm avatar djlauk avatar e111077 avatar felixschusi avatar graynorton avatar jordanaustin avatar justinfagnani avatar keanulee avatar kevinpschaaf avatar larsdenbakker avatar ljmerza avatar lostinbrittany avatar nicolejadeyee avatar rictic avatar samthor avatar skyisthelimit avatar timvdlippe avatar toddpress avatar usergenic avatar web-padawan avatar westbrook avatar yuinchien avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lit-element's Issues

Performance

Is the stamp of a lit-html element faster then the stamp of a polymer element?

How to pass Objects as properties

I am following a controller as attribute pattern (coming from Angular world):

const DEFAULT_TEXT = 'This is the default Text';
export class ButtonController {
    constructor(public text, 
                public color, 
                public onClick: () => void) {
        
    }
    public reset() {
        this.text = DEFAULT_TEXT;
    }
}
export class ButtonComponent extends LitElement {
    static get properties() {
        return {
            ctrl: ButtonController
        };
    }
}
customElements.define('bk-button', ButtonComponent);

Any ideas on how can I pass an instance of ButtonController to <bk-button ctrl=btnCtrl></bk-button>.

Adding reflectToAttribute to the demo doesn't work

      static get properties() {
        return {
          foo: String,
          bar: Number,
          whales: { type: Number, reflectToAttribute: true }
        }
      }
whales: ๐Ÿณ๐Ÿณ๐Ÿณ๐Ÿณ๐Ÿณ๐Ÿณ๐Ÿณ
          
$0.whales
7
$0.getAttribute("whales")
"0"

Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new'

I'm trying out Lit Element in a vanilla Angular 6 project and running into Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new' when trying out the hello world lit element example. This commit shows how I added webcomponentjs / litelement packages, allow custom schema in angular, declare the my-element LitElement example, and then use that element in the app. That commit was made right after running the ng new command.

screen shot 2018-05-11 at 3 33 16 pm

If you want to poke at it, run the following commands...

git clone https://github.com/rjsteinert/angular-with-lit-element.git
cd angular-with-list-element
npm install
npm start

Export svg from lit-extended as well as html

I've been trying to use lit-element to render svg icons within a component, but found it strange to have to import svg from lit-html. I had some trouble getting the right version of both dependencies in sync so that rendering would work right.

I think it makes sense to import both rendering functions from the same place and not have to install a separate dependency with all the versioning headaches that causes.

Need for context properties

I like the turn project took, and I suppose Redux is going to be mainstream in this area. And there is one thing that might improve the way LitElement works with Redux.

This idea is not unique, React also has it.

Now, in order pass a property down the hierarchy, each component needs to define it and pass over to its children

Better approach might be to have context properties that will be available for all affected scope/branch it will be applied.

I am not sure about implementation, but maybe scoped custom element registry and WeakMap might come in handy?

And it will be possible to have this sort of code

my-component-container.js

   import MyComponent from './my-component.js';

   const mapStateToProps = state => ({ someState: state.someState });
   const mapDispatchToProps = dispatch =>
            ({ doSomething: (value) => dispatch({ type: 'DO_SOMETHING', payload: value }) });

   export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);

my-component.js

   ...
   export default class MyComponent extends LitElement {
        static get properties() {
            return {
               someState: String,
               doSomething: Function,
            };
        }
        _render({ someState, doSomething }) {
           return html`<input value=${someState} on-change=${doSomething}/>`;
       }
   };

connect.js

   export const connect = (mapStateToProps, mapDispatchToProps) => baseElement => {
       return class extends baseElement {
           connectedCallback() {
                const { store } = this.context;
                if (!store) {
                   throw new Error('no store passed over');
                }
                this.__storeUnsubscribe = store.subscribe(() => this._stateChanged(store.getState()));
                ....
           }

           disconnectedCallback() {
              if (this.__storeUnsubscribe) {
                  this.__storeUnsubscribe();
              }
               ...
           }
       }
   }

index.html

   <store-provider>
      <my-component></my-component>
   </store-provider>
   <script>
      import { createContext } from  '@polymer/lit-element';
      createContext('store-provider', { store: createStore() }));
   </script>

Accesing element instances

What is the recommended approach for retrieving instances of elements after they are instantiated?
My questions arises from the need of having configurable properties on classes/elements.
In some cases it is undesirable to specialize (using implementation inheritance) a class. Let us assume we only need to change one property or method in each sub class, in e.g:
class DataTable extends LitElement
class ProductDataTable extends DataTable
class UserDataTable extends DataTable

In this example all the tables have the same behavior except of how the data is fetched. If I could pass a custom fetch function to each DataTable my problem would be solved. Having access to the element instance of the DataTable this would be no issue. If I create an element by placing the custom HTML element tag in the DOM <data-table></data-table>, is the preferred way to query the element directly from the DOM (in e.g. document.querySelector())?

Or should I create an instance of the element programmatically and then insert it in the appropriate place?

const table = new DataTable(...);
table.fetch = getAllUsers; // Or pass it to the constructor as a dependency
document.body.appendChild(table);

[docs] best practices

We get a lot of questions about how elements should be constructed using LitElement and where and how to do various things.

We want to add a best practices document to the wiki here to address some of these questions and put forward some guidance about patterns to use.

Conditional dom-if inside dom repeat

So, I try to make something like this

some-element.js

<dom-repeat items="${cards}" as="item">
  <template>
    <dom-if if="${_isRoyal(item.type)}">
      <template>
        <p>The card is a Royal card!<p>
      </template>
    </dom-if>
  <template>
<dom-repeat>

...
_isActive(e) {
  console.log(e);
}
...

when I do that, the item inside <dom-if if="${_isRoyal(item.type)}"> is not defined.
and when I do this:

<dom-if if="[[_isRoyal(item.label)]]">

for the conditional part, console says that method '_isRoyal' not defined.
any help with this? thanks.

2 way data binding not working

I'm expecting 2 way data binding to work similar to polymer templates but I can't get it to work.
For example using a <paper-toggle-button checked="${toggled}"> only works in one direction (reading, but not writing).

I have also tried <paper-toggle-button checked="[[${toggled}]]"> and <paper-toggle-button checked="[[toggled]]">

Testing out with start-polymer3

Hey! I've repurposed the start-polymer3 codebase and am trying to drop in lit-element.

What's the suggested way to bind the checked state of paper-checkbox with marsfarm-app's pie property?

import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { LitElement, html } from '@polymer/lit-element/lit-element.js';
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/polymer/lib/elements/dom-if.js';
import '@polymer/paper-checkbox/paper-checkbox.js';

class MarsfarmApp extends LitElement {
  static get properties () {
    return {
      message: {
        type: String,
        value: ''
      },
      pie: {
        type: Boolean,
        value: false,
        observer: 'togglePie'
      },
      loadComplete: {
        type: Boolean,
        value: false
      }
    };
  }

  constructor() {
    // If you override the constructor, always call the 
    // superconstructor first.
    super();
    this.message = 'Hello World! I\'m a Polymer element :)';
  }

  ready(){
    // If you override ready, always call super.ready() first.
    super.ready();
    // Output the custom element's HTML tag to the browser console.
    // Open your browser's developer tools to view the output.
    console.log(this.tagName);
  }
  
  togglePie(){
    if(this.pie && !this.loadComplete) {
      // See https://developers.google.com/web/updates/2017/11/dynamic-import
      import('./lazy-element.js').then((LazyElement) => {
        console.log("LazyElement loaded");
      }).catch((reason) => {
        console.log("LazyElement failed to load", reason);
      });
      this.loadComplete = true;
    }
  }

  render() {
    return html`
      <h1>Start Polymer 3.0</h1>
      <p>${this.message}</p>
      <paper-checkbox 
        checked="{{pie}}">I like pie.</paper-checkbox>
      <template is="dom-if" if="${this.pie}">
        <lazy-element><p>lazy loading...</p></lazy-element>
      </template>
    `;
  }

}

// Register the element with the browser.
customElements.define('marsfarm-app', MarsfarmApp);

[edit: added syntax highlighting]

[Firefox] Shady DOM seems to eat td/tr elements

Running a Firefox nightly build from 2018-04-29 2018-05-10, with anything that renders <tr> rows like this (repeat vs .map doesn't matter):

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@next/webcomponents-loader.js"></script>
</head>
<body>
  <script type="module">
    import {LitElement, html} from 'https://unpkg.com/@polymer/lit-element@latest/lit-element.js?module';
    class MyElement extends LitElement {
      _render({ }) {
        return html`<style> .mood { color: green; } </style>
          Web Components are
          <table>
            <tbody>
              ${[ {one: 'dank', two: 'af'} ].map(item => html`
                <tr><td>${item.one}</td><td>${item.two}</td></tr>
              `)}
            </tbody>
          </table>
        `;
      }
    }
    customElements.define('my-element', MyElement);
  </script>
  <my-element></my-element>
</body>
</html>

Everything is fine with Shadow DOM (dom.webcomponents.shadowdom.enabled):

wayland-screenshot-2018-05-10_15-00-30-fs8

But with the polyfill / Shady DOM, the table rows / cells are gone, all text is dumped together into the tbody:

wayland-screenshot-2018-05-10_14-59-14-fs8

Non-shadow dom API

As a long-time user of Polymer, one of my biggest issues with Polymer.Element is it's hard buy-in with shadow dom. There is a method that you can overwrite to avoid creating a shadow root, but you really have to know what you're doing and then there are still issues around styling. Especially on browsers that need shady dom / css.

Shadow dom is a powerful tool and makes a lot of sense for building re-usable UI components. When building large complex applications, it is useful to split code up into separate components But in our experience, using shadow dom for all these private components has a lot of downsides. Closely associated components are unnecessarily isolated making tests more complicated, shared styles are duplicated many times over and especially on browser that do not have native shadow dom performance is negatively impacted. I think in the applications we build, over half our components do not need to use shadow dom.

The current support for elements without shadow dom is to overwrite _createRoot and return 'this'. I'm worried that this is not a very intuitive API and already requires some in-depth knowledge of how this works internally. I'm hoping that there can be more official support for creating elements without shadow dom and that it's use cases are covered by documentation, demos and tests. I'd be happy to contribute this where possible.

[Firefox] Attributes are reassigned if used in styles

If using the attribute values in the style tag, the values of attributes are reassigned between each other. I created a simple demo: Stackblitz Demo

In the demo the relevant code looks like:

_render({top, left, animal, whales}) {
    return html`
      <style>
        :host {
          display: block;
          position:absolute;
          top: ${top}px;
          left: ${left}px;
        }
      </style>
      <h4>Type: ${animal}</h4>
      <div>Whales: ${'๐Ÿณ'.repeat(whales)}</div>
      <p>Top: ${top}, Left: ${left}</p>
      <slot></slot>
    `;
  }

In Chrome it works but in Firefox animal and top, and whales and left will have changed values with each other. Removing top and left from style declaration makes the issue go away.

firefox_bug

npm run build fails by default

src/@polymer/lit-element.ts(14,33): error TS7016: Could not find a declaration file for module '../../@polymer/polymer/lib/mixins/properties-mixin.js'. '/home/kenchris/repo/lit-element-1/node_modules/@polymer/polymer/lib/mixins/properties-mixin.js' implicitly has an 'any' type.
src/@polymer/lit-element.ts(25,10): error TS2339: Property 'attachShadow' does not exist on type 'LitElement'.
src/@polymer/lit-element.ts(32,37): error TS2339: Property '__data' does not exist on type 'LitElement'.
src/@polymer/lit-element.ts(34,27): error TS2339: Property 'shadowRoot' does not exist on type 'LitElement'.
src/@polymer/lit-element.ts(51,10): error TS2339: Property '_invalidateProperties' does not exist on type 'LitElement'.
src/@polymer/test/lit-element_test.ts(47,31): error TS2345: Argument of type 'C' is not assignable to parameter of type 'Node'.
  Property 'attributes' is missing in type 'C'.
src/@polymer/test/lit-element_test.ts(48,18): error TS2339: Property 'shadowRoot' does not exist on type 'C'.
src/@polymer/test/lit-element_test.ts(49,22): error TS2339: Property 'shadowRoot' does not exist on type 'C'.
src/@polymer/test/lit-element_test.ts(50,31): error TS2345: Argument of type 'C' is not assignable to parameter of type 'Node'.
src/@polymer/test/lit-element_test.ts(71,8): error TS2339: Property 'foo' does not exist on type 'HTMLElement'.
src/@polymer/test/lit-element_test.ts(147,8): error TS2339: Property 'foo' does not exist on type 'HTMLElement'.
src/@polymer/test/lit-element_test.ts(148,8): error TS2339: Property 'nextRendered' does not exist on type 'HTMLElement'.
src/@polymer/test/lit-element_test.ts(150,10): error TS2339: Property 'foo' does not exist on type 'HTMLElement'.
src/@polymer/test/lit-element_test.ts(151,10): error TS2339: Property 'nextRendered' does not exist on type 'HTMLElement'.
src/@polymer/test/lit-element_test.ts(153,12): error TS2339: Property 'foo' does not exist on type 'HTMLElement'.
src/@polymer/test/lit-element_test.ts(154,12): error TS2339: Property 'nextRendered' does not exist on type 'HTMLElement'.

Can't set boolean attribute

Please consider this element:

customElements.define('power-fab', class PowerFab extends LitElement {
  static get properties() {
    return {
      label: String,
      title: String,
      active: Boolean,
    };
  }

  toggleActive(event) {
    console.log(this.active); // false
    this.active = !!this.active;
    console.log(this.active); // false
  }

  connectedCallback() {
    super.connectedCallback();
    this.addEventListener('click', event => this.toggleActive(event));
  }

  _propertiesChanged(currentProps, newProps, oldProps) {
    super._propertiesChanged(currentProps, newProps, oldProps);
    this.setAttribute('aria-label', newProps.title);
    newProps.active ? this.setAttribute('active', '') : this.removeAttribute('active');
  }

  render({label = '+', title, active}) {
    return html`
    <span>${label}</span>
    `;
  }
});

When I click on the element, console reports false false! meaning, I can't set a boolean attribute from the event listener.

When I inspect the element in dev tools and run $0.active = true, my attribute is applied however.

If this is PEBCAK, please refer me to documentation. Thanks

Typescript error when 'noImplicitAny' in set to TRUE in tsconfig

node_modules/@polymer/lit-element/lit-element.d.ts(14,46): error TS7016: Could not find a declaration file for module '@polymer/polymer/lib/mixins/properties-changed.js'. '/Users/shihn/work/guild/guild-web/node_modules/@polymer/polymer/lib/mixins/properties-changed.js' implicitly has an 'any' type. Trynpm install @types/polymer__polymerif it exists or add a new declaration (.d.ts) file containingdeclare module 'polymer__polymer';node_modules/@polymer/lit-element/lit-element.d.ts(15,44): error TS7016: Could not find a declaration file for module '@polymer/polymer/lib/mixins/properties-mixin.js'. '/Users/shihn/work/guild/guild-web/node_modules/@polymer/polymer/lib/mixins/properties-mixin.js' implicitly has an 'any' type. Trynpm install @types/polymer__polymerif it exists or add a new declaration (.d.ts) file containingdeclare module 'polymer__polymer';node_modules/@polymer/lit-element/lit-element.d.ts(17,46): error TS7016: Could not find a declaration file for module '@polymer/polymer/lib/mixins/properties-changed.js'. '/Users/shihn/work/guild/guild-web/node_modules/@polymer/polymer/lib/mixins/properties-changed.js' implicitly has an 'any' type. Trynpm install @types/polymer__polymerif it exists or add a new declaration (.d.ts) file containingdeclare module 'polymer__polymer';node_modules/@polymer/lit-element/lit-element.d.ts(18,44): error TS7016: Could not find a declaration file for module '@polymer/polymer/lib/mixins/properties-mixin.js'. '/Users/shihn/work/guild/guild-web/node_modules/@polymer/polymer/lib/mixins/properties-mixin.js' implicitly has an 'any' type.

Goes away if noImplicitAny is FALSE. I'd like it to be true in my projects - because typed

_render?

What's the reason for using the leading _ there?

On IE11 including styles with css custom properties breaks all styling

NOTE, this occurs on any browsers that require ShadyCSS's css custom properties shim. This is currently only IE11 or older browser versions.

This is a limitation of lit-html's shady-render module. There is somewhat of a workaround, but it will only work correctly if the element has a style elements in one lit-html template, you will not be able to share styles in template parts with this workaround.

connectedCallback() {
  super.connectedCallback();
  if window.ShadyCSS) {
    window.ShadyCSS.styleElement(this);
  }
}

How to get data from 2-way binding component

Since lit-element use unidirectional data binding, for ex: <p>${myprops}</p> . How do I get a data from a component which in its pattern use 2-way binding in LitElement? for example in routing <app-route/> component with PolymerElement

<app-route
    route="{{route}}"
    pattern="/:page"
    data="{{pageRoute}}">
</app-route>

And the data is propagated (I dont exactly know how this works) to pageRoute.page,

<iron-pages selected="[[pageRoute.page]]" attr-for-selected="page-name" fallback-selection="fallback">
    <div page-name="test">Test</div>
    <div page-name="fallback">Not found</div>
</iron-pages>

Coexistence with Polymer 2 components?

Hi!

There is a way to use polymer 2 components inside a LitElement?

Before yesterday, using the importHref function from polymer 3, I used to be able to load html webcomponents, and load them inside the render() with a tag, but now, with this commit,
https://github.com/Polymer/polymer/commit/fd416a212ed725eef26d3b29bb624ed66669ad76
I am not able anymore to do that.

I have a scenario where I can't migrate polymer 2 components, but I have to use them, so I wonder if its possible to use polymer 2 components (html files) inside a litElement

how do you re-render with litelement?

So I've been playing around with polymer for the first time in the last 2 days so I'm new to this framework but I'm very experienced with react... now I can't seem to find away to re-render the html no matter what I do. Also the methods this.set, this.notifyPath, this.push don't work.

here's what i'm working on stackblitz so you can tell me what am I do wrong
https://stackblitz.com/edit/lit-element-example-zkxtyl

Support or document non-generated accessors.

We should make sure that handwritten accessors are fully supported, documented, and tested.

I assume this much works to delegate state to Polymer, but does it properly call render()?

class MyElement extends LitElement {
  get foo() { return this._getProperty('foo'); }
  set foo(v) { this._setProperty('foo'); }

  render() {
    return html`foo: ${this.foo}`;
  }
}

Webpack : Lit Element new usage

Hi everyone, what's up?

As Polymer 3 came out, I try to use it along with Webpack in order to ease my frontend logic, the problem is, if I try to "compile" the Polymer Lit Element with Webpack, I receive this error :

LitElement

Here's my element class :

import { LitElement, html } from '@polymer/lit-element';

class HomeComponent extends LitElement {

    static get properties() {
        return {
            foo: String,
        }
    }

    _render(props) {
        return html`
            <div>Hello From Polymer !</div>
        `;
    }
}

customElements.define('my-element', HomeComponent);

And here's my Webpack configuration :

const Encore = require('@symfony/webpack-encore');

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .cleanupOutputBeforeBuild()
    .enableSourceMaps(!Encore.isProduction())
    // uncomment to create hashed filenames (e.g. app.abc123.css)
    // .enableVersioning(Encore.isProduction())
    .enableTypeScriptLoader()
    .enableVueLoader()
    .enableSassLoader()
    .addLoader(
        {
            test: /\.scss$/,
            use: [
                {
                    loader: 'sass-loader',
                    options: {
                        importer: function(url, prev) {
                            if(url.indexOf('@material') === 0) {
                                const filePath = url.split('@material')[1];
                                const nodeModulePath = `./node_modules/@material/${filePath}`;
                                return {
                                    file: require('path').resolve(nodeModulePath)
                                };
                            }
                            return {
                                file: url
                            };
                        }
                    }
                }
            ]
        }
    )
    .addLoader(
        {
            test: /\.js$/,
            loader: 'babel-loader',
            query: {
                presets: ['es2015']
            }
        }
    )

    // Style
    .addStyleEntry('core', './assets/scss/public/core.scss')
    .addStyleEntry('registration', './assets/scss/public/registration.scss')

    // Javascript
    .addEntry('form', './assets/javascript/components/form.js')
    .addEntry('snackbar', './assets/javascript/components/form/snackbar.js')

    // PWA
    .addEntry('serviceWorker', './assets/javascript/pwa/app.js')
    .addEntry('sw', './assets/javascript/pwa/sw.js')

    // Vue
    .addEntry('vue', './assets/vue/public/index.js')

    // Polymer
    .addEntry('home', './assets/javascript/polymer/home.js')
;

module.exports = Encore.getWebpackConfig();

Information: Encore is a PHP/Symfony library, that's just a wrapper around Webpack so the call stay easily the same.

Does anyone have more information about the Webpack usage with lit-Element ?

Thanks for the help :)

Using lit-element with dom-if

I am sure this is an issue the Polymer team is aware of but I wanted to open this to make sure.

Using dom-if in a lit-element is not working as expected. For instance,

_render(props) {
  return html`
    <dom-if if="${props.shouldRenderThis}">
      <template>
        <mwc-button label="add" on-click="${_ => this.addFunction()}"></mwc-button>
      </template>
    </dom-if>
  `;
}

This will render and visually not broken, but if one clicks on the <mwc-button> the on-click event-listener is not triggered, therefore the addFunction is not called.

And lit-element doesn't really propose a solution, at least not a user-friendly one AFAIK. The work-around I am using right now is something similar to :

_render(props) {

  let addButton = html``;
  if (props.shouldRenderThis) {
    addButton = html`
      <mwc-button label="add" on-click="${_ => this.addFunction()}"></mwc-button>
    `;
  }

  return html`
    ${addButton}
  `;
}

Is there a better solution to create conditional templates in lit-element ? Or is there a working branch already trying to leverage this question ?

Thanks Polymer.

Support mixins of official Polymer Elements

Right now lit-element is not compatible with mixins of elements which makes it close to impossible to use it in a production app since you cannot style elements as intended.

It would be great to get support for this soon so we can start using lit-element in production.

Change `render()` -> `renderCallback()`

Experimenting with a lit-element I faced a problem that looks quite little but breaks the currently existing developer experience.

As a react developer I used to use any prop with any name because every props are encapsulated in props object inside a React component. But WebComponents are different. All properties are properties of a component itself, so there is a possibility of naming conflict. And the biggest one I have is conflict happened during implementation of render props approach.

It is a kind of convention in React world to use children or render property to implement this approach. I can use the following code:

class App extends React.Component {
  render() {
    return (
      <MyComponent>
        {(props) => <div {...props}/>}
      </MyComponent>
    );
  }
}

or

class App extends React.Component {
  render() {
    return (
      <MyComponent
        render={(props) => <div {...props}/>}
      />
    );
  }
}

The first approach is not applicable for WebComponents due to their implementation, but the second is fair enough. However, this is a point where naming conflict happens.

Due to a main method of lit-element with name render I am unable to provide the same property, so I have to change this property, destroying the previous user experience.

That's why this proposal exists. I would suggest to replace render method with renderCallback, as it was done for basic lifecycle methods of WebComponents (connectedCallback, disconnectedCallback, etc.). It would resolve the possibility of naming conflict and allow to use render property along with render method, and would look like following:

class MyComponent extends LitElement {
  static get is() {
    return 'my-component';
  }

  static get properties() {
    return {
      foo: String,
      render: Function,
    }
  }

  renderCallback({foo, render}) {
    return html`<div>${render(foo)}</div>`
  }
}

class App extends LitElement {
  renderCallback() {
    return html`<my-component
      render=${(foo) => html`<span>${foo}<span>`}
    ></my-component>`
  }
}

I think the same approach can be applied for other methods that can conflict with possible property names.

Another possible approach is to make these methods protected and start their names with underscore. They already are protected by design since the only purpose of them is to be called by parent class LitElement. So they could look like following:

class MyComponent extends LitElement {
  static get is() {
    return 'my-component';
  }

  static get properties() {
    return {
      foo: String,
      render: Function,
    }
  }

  _render({foo, render}) {
    return html`<div>${render(foo)}</div>`
  }
}

Thanks for the attention.

Styles are not rendered in the same order as what is specified in lit-html template

Consider this:

import { LitElement, html } from '@polymer/lit-element';
import '@polymer/iron-icon/iron-icon.js'; // 3.0.0-pre.12

const SharedStyles = html`<style>button {background: blue;}</style>`;
class MyApp extends LitElement {
  render() {
    return html`
    ${SharedStyles}
    <style>button {background: red;}</style>
    <button>Should be red</button>
    `;
  }
}

If you run the above you will see the SharedStyles style element is placed after the normal <style> element so button has background: blue instead of background: red.

Note that if you comment out Polymer3's iron-icon.js import then it works fine. Also this seems to start happening in 0.3.0 release which has ShadyCSS support.

cc @graynorton

How to get child element by id ?

How to get a specific child element by id. In the following example I would like to get the canvas child element in order to draw something on it:

class MyElement extends LitElement {

      _render() {
        return html`
            <canvas id="draw"></canvas>
        `;
      }

}

With Polymer elements I used to get the child element with this.$.draw but it's not working with LitElement. What is the workaround ?

lit-element breaks with polymerElement / css mixin imported via js

I have created a repo with a small reproduction here. I'm not sure if this error is generally happening or I'm doing something wrong here (don't think so though).

Repro instructions and sample can be found here:
https://github.com/AndreasGalster/lit-css-prop-error

My app was working just fine until I've upgraded from lit-element 0.2 to 0.4, or 0.5

Expected Result:

App shell won't throw an error

Actual Result:

Lit-element breaks with a prop error:

Uncaught TypeError: Cannot read property '1' of null
    at new Template (lit-html.js:265)
    at eval (shady-render.js:34)
    at render (lit-html.js:129)
    at render (shady-render.js:40)
    at HTMLElement._applyRender (lit-element.js:190)
    at HTMLElement._propertiesChanged (lit-element.js:140)
    at HTMLElement._flushProperties (properties-changed.js:339)
    at HTMLElement._flushProperties (lit-element.js:150)
    at HTMLElement.ready (properties-changed.js:183)
    at HTMLElement.ready (lit-element.js:78)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.