Buslowicz / twc

TypeScript based, boilerplate-less, Polymer toolbox friendly Polymer Modules
32 stars 1 forks source link

Template expressions #100

Open Buslowicz opened 7 years ago

Buslowicz commented 7 years ago

Polymer itself relies on simple data binding, and does not provide expressions. TWC can fulfill those gaps, but it's not as trivial to design as one would think. There are few things that need to be discussed in order to create a solid workflow. These are:

I'd love to implement a solution that works for every use case, but I'm out of ideas. This is why I ask for help in designing the expressions. I know some of us will not like the idea of expression binding, but for others it might be a live saver, so please cooperate (it's an optional feature anyway).

cbfranca commented 7 years ago

It can be realy useful. Sometimes i want to do a simple comparsion expression like {{ item.age > 30 }} but can't. So let's talk about that.

👍

Buslowicz commented 7 years ago

Uhm, ok now I see I mixed 2 concepts here ^^ one is expressions, the other one is using string templates. Sooo, the markup. Totally agree with superfluity of {{ }}, two-way binding will have no effect on that. As for the [[ ]], sounds good, though I'm afraid people might not like the confusion between original binding and expressions. My old idea (back at typed-polymer) was using {{{ }}}, what do you think about [[[ ]]]? Or should we better stay with [[ ]]?

The 3rd point was a bit my own confusion. As for now, I have implemented simple expressions when using template() method to return a template string. There it's possible to use ${this.whatever > 18} etc. I was wondering how to make this work with <dom-repeat>.

Now about binding and point 2 - global variables. Should we allow to use globals? Like <h1>Title: [[document.title]]</h1>? If so, how should we distinguish globals from template variables (like item of <dom-repeat>) so it's intuitive? Or should we not allow those and have globals passed through properties/computed properties?

tpluscode commented 7 years ago
  1. If possible I'd keep both binding syntaxes much as Polymer allows either. I assume that it could be difficult to decide whether a binding is Polymer-native or two expression?
  2. Again, ideally, the expression should always operate on exactly the same variables that any Polymer binding does.
  3. Ditto, I think expressions should be implemented as straightforward as converting it to a computer function. This would keep the Polymer scope intact. Modifying that scope would be a mistake IMO
Buslowicz commented 7 years ago
  1. Detecting what is expression and what is pure binding wouldn't be that difficult. TS Compiler API would help us here.
  2. :+1:
  3. I wasn't talking about modifying the state, but more about using template string with variables to aid types. This however looks for me now as a completely different task and a discussion :).

So, if I understand correctly, we want something more less like this:

<dom-if if="[[titleProp !== "default"]]">
    <template>
        <button title=[[titleProp]]>OK</button>
    </template>
</dom-if>

Does it look all right? Anything to change/add/remove?

Also another question: what kind of expressions do we want? From basic expressions we can have:

Anything I am missing? Or should we also have more complex expressions?

nborelli commented 6 years ago

Honestly, I am not sure that this is the right thing to do. Beyond the philosophical discussion about whether this sort of stuff should be done in the class as a calculated value, I would be concerned about possibly not being in alignment with the Polymer library in the future. What would happen if the Polymer team decided to add their own template expressions in a future release?

The value of your library is that you are providing a clean approach for using Polymer and TypeScript together. To that end, I believe that the following items would be more helpful.

  1. Extend the Polymer-CLI to scaffold a project using TWC and TypeScript.
  2. Extensive documentation and getting started guide.

Rant follows, so you could skip this!!

For the Polymer team, I really think they need to focus on the following issue:

It looks like the HTML Import specification implementation is on hold with several browser teams like Safari, FireFox and Edge (see https://www.webcomponents.org) who are concerned that it overlaps with ES2015 import syntax and is not really needed. I tend to agree with the browser vendors on this. We already have a way to async load scripts and the HTML import is not really needed if we can provide the template though a function in the class or add a function to a class using a decorator in the case of TypeScript. Untimately, we are just trying to register a constructor function with a tag name, so the browser can create the correct class for the browser tag. It seems like this can all happen in JavaScript without resorting to the module syntax.

Now, I understand why TWC is generating the HTML file. The Polymer / Web Component community has been trained to use HTML imports and TWC want to generate a module that is compatible with this design. TWC could probably generate a simpler HTML module that does all the work in the JavaScript and simply does not contain a template in the XML, but I need to think about that a bit more. It sure would be nice if I could import some TypeScript decorators from TWC and write a TypeScript file and not need the TWC CLI at all. I might be missing something, but I just do not understand the need for HTML imports when we can already import JavaScript synchronously or asynchronously.

Sorry, if it seems like I am off on a tangent, but I really do believe that you are trying to fill a gap that the Polymer team really should be addressing going forward.

Buslowicz commented 6 years ago

Regarding expressions. It's true, providing additional layer of abstraction may in the future conflict with original Polymer. However, if they do provide such feature (highly unlikely, considering the #UseThePlatform motto), I will update TWC to work with it :). I do however understand what you are saying and am not insisting on that feature, though would even personally greatly appreciate it. As for documentation and polymer-cli extension, docs are on the way, and cli extension will come soon (will add a task to create a generator).

Regarding HTML imports and the outputs. I completely agree that with components as classes with string template, we do not need anything but ES imports. The reason to have those though, is writing templates in HTML files (not every editor supports syntax highlighting inside of a string and some people might not want to use a build tool). Nevertheless, I will experiment with custom build process and will add an output target to be a JS file. Anyway, this is a very good discussion, but for a different issue. You could (and I'd be thankful) create an issue with the ideas and I'll be happy to discuss that and maybe implement :).

tpluscode commented 6 years ago

Regarding expressions I too was skeptical at first but I think they are a good fit for TWC. Any non-Polymer exlression would be translated into a compute function. You allow extra features without deviating from standard Polymer. Unlike PolymerTS which generated something very different.

Regarding imports. This is a sensitive subject and the Polymer team too would like to be in a different place. But the reality we got is that the two kinds of imports are incompatible and ES modules simply aren't ready yet. Thus, I understand why the Polymer team did what the did.

And about the output of TWC. If it is to remain a TypeScript syntactic sugar for Polymer, it should output something as close to handmade Polymer as possible. Otherwise it would be repeating PolymerTS and again losing support of the Polymer CLI tooling

Buslowicz commented 6 years ago

We could always decide on [[[ ]]] syntax, which probably wont be used in Polymer itself. As for output, I was more thinking of a 3rd target, so we could compile to Polymer v1 native, Polymer v2 native and Polymer v2 JS. Anyway, that is not for this discussion :P.

Buslowicz commented 6 years ago

Back to this topic. With lit-html coming out soon, I think it would be reasonable to adopt its syntax together with directives etc. What do you guys think?

tpluscode commented 6 years ago

I don't know. Would it not introduce a dependency on lit-html?

Buslowicz commented 6 years ago

Not really, no. It would only introduce the syntax, TWC would still analyze that and output whatever we want. It would only require types for directives. Also this has 1 downside: 1-way binding only.

tpluscode commented 6 years ago

Maybe twc can extend lit-html syntax with 2-way binding which would be turned into listeners and setters?

There's also the difference in how @template decorator work. Currently templates they are implicitly connected to the instance. With lit-html you'd need a function with the element as parameter. Would you have something like below?

@template((host: LitTwcElement) => html`<span>${host.title}</span>`)
class LitTwcElement {
  title = 'I am lit'
}
Buslowicz commented 6 years ago

I was thinking more about the render method for the component, but the above solution looks not bad. I would only change it to

@template((this: LitTwcElement) => html`<span>${this.title}</span>`)
class LitTwcElement {
  title = 'I am lit';
}

As for extending lit syntax, I would prefer to avoid adding custom syntax/methods, though seems like it might be necessary if we want to achieve this. Yet it will not be highest priority right now. Anybody else have a thought on that?