Discussion:
[dart-misc] Html templating in Dart (lit-html alternative)
Greg Lowe
2017-11-10 23:51:44 UTC
Permalink
I was looking at lit-html, and was wondering if it is posible to implement
something similar in Dart, except specifying the html templates using Dart
syntax rather than html inside literals. i.e. A similar syntax to how
flutter builds UI components.

I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).

Below is a rough example of what I mean. This will look better if Dart gets
rest arguments at some point.

I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.

I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html

I know some people prefer html syntax and will be horrified by using Dart
syntax for html - but another library can solve the the html use case -
each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.

import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render, bind,
repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;


TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));


TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);


main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}


class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}


class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Matan Lurey
2017-11-10 23:59:28 UTC
Permalink
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to implement
something similar in Dart, except specifying the html templates using Dart
syntax rather than html inside literals. i.e. A similar syntax to how
flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of these
"immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if Dart
gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using Dart
syntax for html - but another library can solve the the html use case -
each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render, bind,
repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.

Of course if you want data-binding you'd need either:
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.

There are a couple of existing libraries in this area:
* OverReact <https://pub.dartlang.org/packages/over_react> (most production
ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
Post by Greg Lowe
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Tobe Osakwe
2017-11-11 00:25:25 UTC
Permalink
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
Incremental DOM and found it to work decently well:
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of these
"immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if Dart
gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using Dart
syntax for html - but another library can solve the the html use case -
each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render, bind,
repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
Post by Greg Lowe
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-11 00:58:25 UTC
Permalink
Looks pretty good.

What I'm looking for is something where I can code completion in my IDE and
has the same syntax as plain Dart code.

i.e. div(id: "foo", children: [ span(text: "bar") ])

This is probably a hard problem because I assume dart2js or DDC will not
generate decent code for functions with 100+ arguments - I haven't checked
though. This is why I wonder if it makes sense to use Dart compatible
syntax at IDE time, but to compile it to something else behind the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if Dart
gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using
Dart syntax for html - but another library can solve the the html use case
- each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render, bind,
repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
Post by Greg Lowe
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Matan Lurey
2017-11-11 01:05:22 UTC
Permalink
Depends if the auto-complete is that important to you, for example:


* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.

Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.

Another idea would be some sort of "builder" syntax:

*div((b) => b..id = 'foo')*

Where "b" here is "DivBuilder", and is represented by some auto-generated
facade:


* class DivBuilder extends DomBuilder { set id(String id) => this['id']
= id;*

* // ... }*

Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my IDE
and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will not
generate decent code for functions with 100+ arguments - I haven't checked
though. This is why I wonder if it makes sense to use Dart compatible
syntax at IDE time, but to compile it to something else behind the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if Dart
gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using
Dart syntax for html - but another library can solve the the html use case
- each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render, bind
, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-11 01:19:25 UTC
Permalink
Good points.

Could provide an escape hatch for non-standard attributes and data
attributes.

div(id: "foo", attrs: {"--webkit-special": "bar"})

I don't think any of this requires advanced meta programming. I think a
simple build step is enough.

Let's assume I have a build step which takes the following:

TemplateResult fooTemplate(String id, String value) => div(id: bind(id),
children: [span(text: bind(value))]);

And turns it into:

const String fooTemplateParts = ['<div id="', '"><span>', '</span></div>'];

TemplateResult fooTemplate(String id, String value) =>
lit.html(fooTemplateParts, [id, value]);

lit.html is just the html javascript function directly from the javascript
function lit-html.

I believe this is all that is required to make this work.

Of course if the entire lit-html library is rewritten in/for Dart then
other possibilities may emerge.
Post by Matan Lurey
* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.
Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.
*div((b) => b..id = 'foo')*
Where "b" here is "DivBuilder", and is represented by some auto-generated
* class DivBuilder extends DomBuilder { set id(String id) =>
this['id'] = id;*
* // ... }*
Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my IDE
and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will not
generate decent code for functions with 100+ arguments - I haven't checked
though. This is why I wonder if it makes sense to use Dart compatible
syntax at IDE time, but to compile it to something else behind the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if Dart
gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using
Dart syntax for html - but another library can solve the the html use case
- each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render,
bind, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Matan Lurey
2017-11-11 01:29:57 UTC
Permalink
Ah I see what you mean. It's definitely possible.

Today we have the restriction that you can't modify user-authored code as
part of the build process, so you could do:


* // Generated by looking at all functions that return
`TemplateResult`. part 'my_file.g.dart';*

* // Always true, so in dart2js the expression will be
tree-shaken/folded.*
* const $G = true;*

* TemplateResult fooTemplate(String id) {*

* return $G ? _$fooTemplate(id) : div( id: ...,*
* children: ...,*
* );*
* }*

... basically, always use the generated function, but keep the "syntax" for
your "nice" code next to the function you're going to be using/calling, and
generate a _$<name> function for every <name> function returning
TemplateResult.

Yes this is hacky, but you could get a proof of concept working and we
could always have more options for codegen in the future. If you or someone
else reading is interested, our codegen platform is currently here:

https://github.com/dart-lang/build

And we have various utilities here:

https://pub.dartlang.org/packages/source_gen

Let me know if you have any other questions!
Post by Greg Lowe
Good points.
Could provide an escape hatch for non-standard attributes and data
attributes.
div(id: "foo", attrs: {"--webkit-special": "bar"})
I don't think any of this requires advanced meta programming. I think a
simple build step is enough.
TemplateResult fooTemplate(String id, String value) => div(id: bind(id),
children: [span(text: bind(value))]);
const String fooTemplateParts = ['<div id="', '"><span>', '</span></div>'
];
TemplateResult fooTemplate(String id, String value) =>
lit.html(fooTemplateParts, [id, value]);
lit.html is just the html javascript function directly from the javascript
function lit-html.
I believe this is all that is required to make this work.
Of course if the entire lit-html library is rewritten in/for Dart then
other possibilities may emerge.
Post by Matan Lurey
* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.
Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.
*div((b) => b..id = 'foo')*
Where "b" here is "DivBuilder", and is represented by some auto-generated
* class DivBuilder extends DomBuilder { set id(String id) =>
this['id'] = id;*
* // ... }*
Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my IDE
and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will not
generate decent code for functions with 100+ arguments - I haven't checked
though. This is why I wonder if it makes sense to use Dart compatible
syntax at IDE time, but to compile it to something else behind the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if
Dart gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so
just putting this out there to see if anyone else is interested in
experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using
Dart syntax for html - but another library can solve the the html use case
- each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render,
bind, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
tatumizer-v0.2
2017-11-11 03:37:28 UTC
Permalink
Interestingly, we discussed very similar idea here long before javascript
came up with tagged string literals. It's not identical, but the idea is
the same: call user-defined function to concatenate the parts of the
literal.
https://groups.google.com/a/dartlang.org/d/msg/misc/8udHkvN_AjA/-3LgVXII1V4J

Speaking of the above example: "children" is what makes it boring to write,
and difficult to read. I mean, you are trying hard to improve it, go in
great lengths with code generation, but still, "children" remains an
eyesore.
(for the proof, look no further than Flutter examples)
It can be fixed by adding support for named vararg (as discussed recently)
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-11 03:56:14 UTC
Permalink
Agreed, children can be a pain ;) With flutter becoming more popular
varargs is surely on the radar.

i.e.
https://groups.google.com/a/dartlang.org/d/msg/misc/7GUs8zg1C6w/DlsMxiuVAQAJ

I think even without varargs I prefer this style over writing html inside
string literals - choose your poison I guess.

Varargs issue: https://github.com/dart-lang/sdk/issues/16253
Post by tatumizer-v0.2
Interestingly, we discussed very similar idea here long before javascript
came up with tagged string literals. It's not identical, but the idea is
the same: call user-defined function to concatenate the parts of the
literal.
https://groups.google.com/a/dartlang.org/d/msg/misc/8udHkvN_AjA/-3LgVXII1V4J
Speaking of the above example: "children" is what makes it boring to
write, and difficult to read. I mean, you are trying hard to improve it, go
in great lengths with code generation, but still, "children" remains an
eyesore.
(for the proof, look no further than Flutter examples)
It can be fixed by adding support for named vararg (as discussed recently)
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-11 03:41:07 UTC
Permalink
Thanks for the tips, that approach makes sense.

The only think I can't really figure out is how to get the types right in
the IDE without union types.

Ideally I'd be able to something like this:

div({
String|StringBinding className,
Map<String,String|StringBinding> attrs,
List<Element|ElementBinding> children, ...})

But I guess using dynamic for the types isn't totally awful, as at least
you get the IDE completions for parameter names which is most of the
problem.

Or maybe generic method trickery will be enough... I guess you may not even
need to specify the type at a call site as type inference should be able to
figure that out.

T bind<T>(dynamic value) {}

Anyways... plenty to think about.
Post by Matan Lurey
Ah I see what you mean. It's definitely possible.
Today we have the restriction that you can't modify user-authored code as
* // Generated by looking at all functions that return
`TemplateResult`. part 'my_file.g.dart';*
* // Always true, so in dart2js the expression will be
tree-shaken/folded.*
* const $G = true;*
* TemplateResult fooTemplate(String id) {*
* return $G ? _$fooTemplate(id) : div( id: ...,*
* children: ...,*
* );*
* }*
... basically, always use the generated function, but keep the "syntax"
for your "nice" code next to the function you're going to be using/calling,
and generate a _$<name> function for every <name> function returning
TemplateResult.
Yes this is hacky, but you could get a proof of concept working and we
could always have more options for codegen in the future. If you or someone
https://github.com/dart-lang/build
https://pub.dartlang.org/packages/source_gen
Let me know if you have any other questions!
Post by Greg Lowe
Good points.
Could provide an escape hatch for non-standard attributes and data
attributes.
div(id: "foo", attrs: {"--webkit-special": "bar"})
I don't think any of this requires advanced meta programming. I think a
simple build step is enough.
TemplateResult fooTemplate(String id, String value) => div(id: bind(id),
children: [span(text: bind(value))]);
const String fooTemplateParts = ['<div id="', '"><span>', '</span></div>'
];
TemplateResult fooTemplate(String id, String value) =>
lit.html(fooTemplateParts, [id, value]);
lit.html is just the html javascript function directly from the
javascript function lit-html.
I believe this is all that is required to make this work.
Of course if the entire lit-html library is rewritten in/for Dart then
other possibilities may emerge.
Post by Matan Lurey
* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.
Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.
*div((b) => b..id = 'foo')*
Where "b" here is "DivBuilder", and is represented by some
* class DivBuilder extends DomBuilder { set id(String id) =>
this['id'] = id;*
* // ... }*
Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my IDE
and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will
not generate decent code for functions with 100+ arguments - I haven't
checked though. This is why I wonder if it makes sense to use Dart
compatible syntax at IDE time, but to compile it to something else behind
the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would
be required (but maybe there are some more creative hackers out there who
have a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if
Dart gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so
just putting this out there to see if anyone else is interested in
experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using
Dart syntax for html - but another library can solve the the html use case
- each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render,
bind, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-13 21:55:37 UTC
Permalink
(Apologies if you get this twice - groups ate the first one.)

I agree some of the template building could be done as a build time step.
I'm not convinced it will be much of a bottleneck compared to a react
render. On first render a single tree walk of a template node is likely to
be similar or less work than an initial react full render. Subsequent
rerenders can then be much quicker as only the template parts need to
checked and not the entire dom. Will be interesting to see how the
performance pans out. I agree it's always worth being sceptical until the
numbers are in.

What's the advantage of having a second element tree and synthetic events
vs having a single tree, i.e. the dom, and using native dom events? I don't
understand this - a single tree seems better to me.

i.e. I can already do this using the dom.

void clickListener(listener, child) => html('<div
on-click="${listener}">${child}</div>');

or

void clickListener(listener, child) => daml(div(on_click: $(listener),
child: $(child)));

Btw - both of these examples should actually work with the code in the
lit_example repo.
The `div()(...)` syntax was an interesting experiment, but it doesn't look
great and it's hard to format correctly. I'm in the process of replacing
that now with something which looks more or less like Flutter.
new Div(id: 'asd', children: [
new Text('testing!'),
]);
One advantage of a virtual tree over templating is that you can have nodes
which don't actually correspond to real dom. For example, adding an event
handler could be done by wrapping the div in a new kind of widget.
new ClickListener(onClick: ..., child: ....);
Anyway...
One big disadvantage I see in lit-html is that since it uses the browser
APIs to parse those template fragments, you're going to basically be
running a "build" step in your user's browser. Probably okay for smaller
apps, but might get noticeable quickly. A code generation solution in Dart
could easily beat the performance of lit-html by doing this work ahead of
time.
Post by Matan Lurey
Ah I see what you mean. It's definitely possible.
Today we have the restriction that you can't modify user-authored code as
* // Generated by looking at all functions that return
`TemplateResult`. part 'my_file.g.dart';*
* // Always true, so in dart2js the expression will be
tree-shaken/folded.*
* const $G = true;*
* TemplateResult fooTemplate(String id) {*
* return $G ? _$fooTemplate(id) : div( id: ...,*
* children: ...,*
* );*
* }*
... basically, always use the generated function, but keep the "syntax"
for your "nice" code next to the function you're going to be using/calling,
and generate a _$<name> function for every <name> function returning
TemplateResult.
Yes this is hacky, but you could get a proof of concept working and we
could always have more options for codegen in the future. If you or someone
https://github.com/dart-lang/build
https://pub.dartlang.org/packages/source_gen
Let me know if you have any other questions!
Post by Greg Lowe
Good points.
Could provide an escape hatch for non-standard attributes and data
attributes.
div(id: "foo", attrs: {"--webkit-special": "bar"})
I don't think any of this requires advanced meta programming. I think a
simple build step is enough.
TemplateResult fooTemplate(String id, String value) => div(id: bind(id),
children: [span(text: bind(value))]);
const String fooTemplateParts = ['<div id="', '"><span>',
'</span></div>'];
TemplateResult fooTemplate(String id, String value) =>
lit.html(fooTemplateParts, [id, value]);
lit.html is just the html javascript function directly from the
javascript function lit-html.
I believe this is all that is required to make this work.
Of course if the entire lit-html library is rewritten in/for Dart then
other possibilities may emerge.
Post by Matan Lurey
* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.
Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.
*div((b) => b..id = 'foo')*
Where "b" here is "DivBuilder", and is represented by some
* class DivBuilder extends DomBuilder { set id(String id) =>
this['id'] = id;*
* // ... }*
Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my
IDE and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will
not generate decent code for functions with 100+ arguments - I haven't
checked though. This is why I wonder if it makes sense to use Dart
compatible syntax at IDE time, but to compile it to something else behind
the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would
be required (but maybe there are some more creative hackers out there who
have a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if
Dart gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so
just putting this out there to see if anyone else is interested in
experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by
using Dart syntax for html - but another library can solve the the html use
case - each to their own. I'd rather not discuss the pros and cons of using
Dart syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render,
bind, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see
https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Justin Fagnani' via Dart Misc
2017-11-17 18:36:27 UTC
Permalink
Hey there, lit-html author and former Dart team member here :)

I commented on https://github.com/dart-lang/sdk/issues/30558 why JavaScript
template literals work so well for this HTML templating. I think general
the technique is a good fit for Dart because it doesn't require any
user-land expression parsing or evaluation, or reflection at all. The
template system only receives static strings and expression values, not the
expression text, but it does lean pretty heavily on unique properties of
template literals.

A few points:

1. Being based on strings is actually important, because:

a. HTML is open ended, so you can't define a function for every possible
tag and attribute.
b. The result is passed to innerHTML of a <template> element, so it's
more direct and efficient to start with strings.
c. Strings parse much faster than generic expressions.

2. Template literals separate static and dynamic portions of a template in
a way that JSX (as usually compiled) and most other builder APIs don't.

An expression like:

html`<div foo=${bar}></div>`;

calls the html() function with an immutable object containing the literal
parts and array of the expression values. Any embedded DSL builder API
trying to achieve the same efficiency will have to have a way to denote the
static and dynamic portions, conceptually like:

const div({'foo': expr bar})

where expr is the inverse of const and delineates a dynamic expression
embedded in a const expression (I know, doesn't quite make sense w/ actual
const semantics) and all the other parts are unchangeable.



The closest thing I can come up with in Dart to preserving the static and
dynamic structures is something like:

class TemplateResult {
final List<String> strings;
final List<*> values;
TemplateResult(this.strings, this.values);
}

const List<String> _myTemplate = const ['<div foo=', '></div>'];
myTemplate(foo) => new TemplateResult(_myTemplate, [foo]);

render() {
return myTemplate('bar');
}

And now you can use TempalteResult.strings as the cache key for template
prep work. But this is pretty unsatisfying because you can't write a
template that looks like HTML anymore.

It's possible to do a variation where you write closures mixed with strings:

List render() {
return ['<div foo=', () => this.foo, '></div>'];
}

Which would be called exactly once, and then the closures would be
re-evaluated on updates (unlike lit-html which just reevaluates the whole
template expression), but this is not very nice to write either.

So I really do think that tagged template literals are a really unique,
surprisingly powerful feature and to get the same benefits and ergonomics
that Dart would need something very similar. Very curious what my old
teammates think :)

Cheers,
Justin
Post by Greg Lowe
(Apologies if you get this twice - groups ate the first one.)
I agree some of the template building could be done as a build time step.
I'm not convinced it will be much of a bottleneck compared to a react
render. On first render a single tree walk of a template node is likely to
be similar or less work than an initial react full render. Subsequent
rerenders can then be much quicker as only the template parts need to
checked and not the entire dom. Will be interesting to see how the
performance pans out. I agree it's always worth being sceptical until the
numbers are in.
What's the advantage of having a second element tree and synthetic events
vs having a single tree, i.e. the dom, and using native dom events? I don't
understand this - a single tree seems better to me.
i.e. I can already do this using the dom.
void clickListener(listener, child) => html('<div
on-click="${listener}">${child}</div>');
or
void clickListener(listener, child) => daml(div(on_click: $(listener),
child: $(child)));
Btw - both of these examples should actually work with the code in the
lit_example repo.
The `div()(...)` syntax was an interesting experiment, but it doesn't
look great and it's hard to format correctly. I'm in the process of
replacing that now with something which looks more or less like Flutter.
new Div(id: 'asd', children: [
new Text('testing!'),
]);
One advantage of a virtual tree over templating is that you can have
nodes which don't actually correspond to real dom. For example, adding an
event handler could be done by wrapping the div in a new kind of widget.
new ClickListener(onClick: ..., child: ....);
Anyway...
One big disadvantage I see in lit-html is that since it uses the browser
APIs to parse those template fragments, you're going to basically be
running a "build" step in your user's browser. Probably okay for smaller
apps, but might get noticeable quickly. A code generation solution in Dart
could easily beat the performance of lit-html by doing this work ahead of
time.
Post by Matan Lurey
Ah I see what you mean. It's definitely possible.
Today we have the restriction that you can't modify user-authored code
* // Generated by looking at all functions that return
`TemplateResult`. part 'my_file.g.dart';*
* // Always true, so in dart2js the expression will be
tree-shaken/folded.*
* const $G = true;*
* TemplateResult fooTemplate(String id) {*
* return $G ? _$fooTemplate(id) : div( id: ...,*
* children: ...,*
* );*
* }*
... basically, always use the generated function, but keep the "syntax"
for your "nice" code next to the function you're going to be using/calling,
and generate a _$<name> function for every <name> function returning
TemplateResult.
Yes this is hacky, but you could get a proof of concept working and we
could always have more options for codegen in the future. If you or someone
https://github.com/dart-lang/build
https://pub.dartlang.org/packages/source_gen
Let me know if you have any other questions!
Post by Greg Lowe
Good points.
Could provide an escape hatch for non-standard attributes and data
attributes.
div(id: "foo", attrs: {"--webkit-special": "bar"})
I don't think any of this requires advanced meta programming. I think a
simple build step is enough.
TemplateResult fooTemplate(String id, String value) => div(id: bind(id
), children: [span(text: bind(value))]);
const String fooTemplateParts = ['<div id="', '"><span>',
'</span></div>'];
TemplateResult fooTemplate(String id, String value) =>
lit.html(fooTemplateParts, [id, value]);
lit.html is just the html javascript function directly from the
javascript function lit-html.
I believe this is all that is required to make this work.
Of course if the entire lit-html library is rewritten in/for Dart then
other possibilities may emerge.
Post by Matan Lurey
* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.
Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.
*div((b) => b..id = 'foo')*
Where "b" here is "DivBuilder", and is represented by some
* class DivBuilder extends DomBuilder { set id(String id) =>
this['id'] = id;*
* // ... }*
Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my
IDE and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will
not generate decent code for functions with 100+ arguments - I haven't
checked though. This is why I wonder if it makes sense to use Dart
compatible syntax at IDE time, but to compile it to something else behind
the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would
be required (but maybe there are some more creative hackers out there who
have a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some
of these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if
Dart gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so
just putting this out there to see if anyone else is interested in
experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by
using Dart syntax for html - but another library can solve the the html use
case - each to their own. I'd rather not discuss the pros and cons of using
Dart syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render,
bind, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42"
)]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see https://groups.google.com/a/da
rtlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/da
rtlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-17 23:45:06 UTC
Permalink
Thanks for the input.

One difference with the JS usecase is that Dart always has a build step. RIP Dartium. If we assume a build step, then Dart's existing template literal is enough.

Btw, the "Daml" syntax that I prototyped, just gets turned into strings by the buildscript. Support for unknown tags should be easy to support, via tag(tagName: "Foo"), or end users can just add their own tag function stub.

I like the idea of a unified markup syntax, rather that html and Dart. (Too much lisp in me perhaps).

Keep up the good work with lit ;) Exciting to see the standards work on this too.

I'm looking forward to seeing some examples of reactive style apps with web components and lit. I can't figure out how invalidation should work with a tree of components.
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Matan Lurey
2017-11-13 17:18:11 UTC
Permalink
Great I'm glad you were able to hack on something :)
The codegen stuff works pretty smoothly. I managed to whack together a
proof of concept pretty quickly and there weren't any big surprises.
I wrote a simple example web app using this codegen. If anyone's curious
https://github.com/xxgreg/lit_example/blob/master/web/main.dart
Beware - loads of crude hacks.
Post by Matan Lurey
Ah I see what you mean. It's definitely possible.
Today we have the restriction that you can't modify user-authored code as
* // Generated by looking at all functions that return
`TemplateResult`. part 'my_file.g.dart';*
* // Always true, so in dart2js the expression will be
tree-shaken/folded.*
* const $G = true;*
* TemplateResult fooTemplate(String id) {*
* return $G ? _$fooTemplate(id) : div( id: ...,*
* children: ...,*
* );*
* }*
... basically, always use the generated function, but keep the "syntax"
for your "nice" code next to the function you're going to be using/calling,
and generate a _$<name> function for every <name> function returning
TemplateResult.
Yes this is hacky, but you could get a proof of concept working and we
could always have more options for codegen in the future. If you or someone
https://github.com/dart-lang/build
https://pub.dartlang.org/packages/source_gen
Let me know if you have any other questions!
Post by Greg Lowe
Good points.
Could provide an escape hatch for non-standard attributes and data
attributes.
div(id: "foo", attrs: {"--webkit-special": "bar"})
I don't think any of this requires advanced meta programming. I think a
simple build step is enough.
TemplateResult fooTemplate(String id, String value) => div(id: bind(id),
children: [span(text: bind(value))]);
const String fooTemplateParts = ['<div id="', '"><span>',
'</span></div>'];
TemplateResult fooTemplate(String id, String value) =>
lit.html(fooTemplateParts, [id, value]);
lit.html is just the html javascript function directly from the
javascript function lit-html.
I believe this is all that is required to make this work.
Of course if the entire lit-html library is rewritten in/for Dart then
other possibilities may emerge.
Post by Matan Lurey
* div({'id': 'foo'})*
... would be trivial, while your example would require lots of named
parameters, and it would be very difficult to keep updated as web standards
evolve/change. What do you do if you need to add `--webkit-special` and it
doesn't exist in your API etc.
Your other idea of dev-time only properties, i.e. some sort of meta
programming would be nice, but we don't currently have a good mechanism to
expose that to anyone - even our own code generation packages cannot edit
existing code or change the Dart language to allow otherwise invalid syntax.
*div((b) => b..id = 'foo')*
Where "b" here is "DivBuilder", and is represented by some
* class DivBuilder extends DomBuilder { set id(String id) =>
this['id'] = id;*
* // ... }*
Dart2JS would tree-shake away unused setters in this scenario.
Post by Greg Lowe
Looks pretty good.
What I'm looking for is something where I can code completion in my
IDE and has the same syntax as plain Dart code.
i.e. div(id: "foo", children: [ span(text: "bar") ])
This is probably a hard problem because I assume dart2js or DDC will
not generate decent code for functions with 100+ arguments - I haven't
checked though. This is why I wonder if it makes sense to use Dart
compatible syntax at IDE time, but to compile it to something else behind
the scenes.
Post by Tobe Osakwe
You might want to check out https://github.com/thosakwe/html_builder.
Technically, the library just produces HTML AST's and includes a "renderer"
that produces HTML strings. However, I was hacking around with the AST and
https://github.com/html_builder_vdom
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would
be required (but maybe there are some more creative hackers out there who
have a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of
these "immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if
Dart gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so
just putting this out there to see if anyone else is interested in
experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by
using Dart syntax for html - but another library can solve the the html use
case - each to their own. I'd rather not discuss the pros and cons of using
Dart syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render,
bind, repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
--
Post by Matan Lurey
Post by Greg Lowe
For other discussions, see
https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it,
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to
http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google
Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Greg Lowe
2017-11-11 00:53:23 UTC
Permalink
Post by Matan Lurey
Doesn't necessarily *need* a build-step
Without a build step I imagine the div function is going to have > 100
named parameters. Not sure if this is practical.

I've looked at overreact and butterfly, and the div()(...) syntax isn't
great, but it is a good work around given the available options.

Note the difference between lit-html and react is that lit separates static
template content from dynamic template content. My example probably wasn't
clear enough.

Consider the following template:

div(className: "foo", text: bind((value) => value.toUpperCase()));

This would get compiled behind the scenes to an html template tag like:

<template><div class="foo">{{ --placeholder-- }}</div></template>

At runtime the template will get stamped into the dom and the placeholder
will be replaced with the evaluated content of the bind expression. If the
dom is updated only the placeholder node will need to be updated. In this
case a single call to div.textContent.
Post by Matan Lurey
Post by Greg Lowe
I was looking at lit-html, and was wondering if it is posible to
implement something similar in Dart, except specifying the html templates
using Dart syntax rather than html inside literals. i.e. A similar syntax
to how flutter builds UI components.
I assume to make this efficient that some type of build step would be
required (but maybe there are some more creative hackers out there who have
a clever idea to avoid this).
Doesn't necessarily *need* a build-step. One of the reasons some of these
"immediate mode" APIs are popular is that they don't require code
generation.
Post by Greg Lowe
Below is a rough example of what I mean. This will look better if Dart
gets rest arguments at some point.
I would love to hack on a prototype, but I'm time constrained, so just
putting this out there to see if anyone else is interested in experimenting.
I recommend reading the lit-html readme to understand how it works.
https://github.com/PolymerLabs/lit-html
I know some people prefer html syntax and will be horrified by using Dart
syntax for html - but another library can solve the the html use case -
each to their own. I'd rather not discuss the pros and cons of using Dart
syntax vs html syntax in this thread.
import 'dart:html' show document;
import "package:dom_template/dom_template.dart" show html, render, bind,
repeat, TemplateResult;
import "package:dom_template/html.dart" show div, input;
TemplateResult inputTemplate(InputField field) =>
html(
div(children: [
div(class: "text-input", text: bind(field.value)),
input(value: bind(field.value)),
]));
TemplateResult formTemplate(Form form) =>
html(
div(children: [
div(
class: "form-title",
children: [
div(text: bind(form.title)),
repeat(form.fields, inputTemplate),
])
])
);
main() {
var form = new Form("Foo", [new InputField("bar", "Bar", "42")]);
render(document.body, formTemplate(form));
}
class InputField {
InputField(this.id, this.label, this.value);
final String id;
final String label;
final String value;
}
class Form {
Form(this.title, this.fields);
final String title;
final List<InputField> fields;
}
Yup, something roughly like that would work for static rendering.
* A framework (with code generation) to watch and update the DOM.
* A DOM differ to take previous/next state and apply the difference.
* Something else.
* OverReact <https://pub.dartlang.org/packages/over_react> (most
production ready, but does use JS interop w/ React)
* Butterfly <https://github.com/yjbanov/butterfly> (prototype-y)
* Uix <https://github.com/localvoid/uix> (abandoned, but the code is there)
Post by Greg Lowe
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups
"Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Loading...