Loading a web component in Dart M2 (web_ui) - dart

Through my journey of dart, I stumbled upon a "blocker" in terms of loading a component.
While having my component defined as followed:
<!DOCTYPE html>
<element name="x-foo" constructor="FooComponent" extends="button">
<template>
<button type="button" class="btn {{classes}}"> {{text}} </button>
</template>
<script type="application/dart">
import 'package:web_ui/web_ui.dart';
String classes = '';
String text = '';
class FooComponent extends WebComponent {
}
</script>
</element>
and referencing the component as followed:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>example</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<!-- '../web/foo.html' or '../web/out/foo.html.dart' -->
<link rel="components" href='foo.html'>
</head>
<body>
<h1>example</h1>
<p>Hello world from Dart!</p>
<x-foo></x-foo>
<script type="application/dart">void main() { }</script>
<script type="text/javascript" src="dart.js"></script>
</body>
</html>
and my build script not creating a html file (output folder: foo.html.dart), I'm not sure to which file I have to reference.
The manual is also not declarative enough to solve my issue:
http://www.dartlang.org/articles/dart-web-components/spec.html#loading-components
Referencing to either the definition of the component (foo.html) or it's generated output (foo.html.dart) is not working. I've also double checked the paths of both files through inspection, which just downloaded both files with chromium.
My concluding question:
Is this reference (link element href) pointing to an internal intelligence or to a "physical" available file at runtime? And if secondly, which one (generated (html/dart) or source)?
To avoid misunderstandings, I've added a list of my repo:
foo
packages
examples
assets
dart.js
example.html
web
out
foo.html.dart
foo.html
build.dart

Component file (foo.html) is missing the <html><body>...</body></html> tags:
<!DOCTYPE html>
<html>
<body>
<element name="x-foo" constructor="FooComponent" extends="button">
...
</element>
</html>
</body>
Both files (examples.html and foo.html) must be in the same base directory:
web
examples.html
foo.html
...
Then, examples.html need be used as argument inside build.dart:
build(new Options().arguments, ['web/example.html']);
And, finally, foo.html (that is, web/foo.html) must be the one to be linked:
<link rel="components" href='foo.html'>

The way you have it in your main HTML file is correct. You reference foo.html because the referencing HTML document needs to be compiled with dwc. dwc will take the main HTML file and compile it and all the the components it includes. The component are completely compiled to Dart and they .html files won't be used anymore.
If you're trying to edit example.html to include your component, you'll need to compile example.html, and not foo.html. You'll still generate foo.html.dart, but also example.html.dart and a bootstrap script to load everything up.

Related

Exception: NoSuchMethodError: method not found: 'whenPolymerReady'

I am using Dart SDK 1.5.3 | polymer 0.11.0+5 | Windows x64. When I create a created a polymer application using the template 'Sample web application using the polymer library (mobile friendly) option' and run the application it works as expected with the counter incrementing when the button is clicked.
Assuming the page with the
<script type="application/dart">
export 'package:polymer/init.dart';
</script>
is index.html, attempting to refactor the application by removing the following lines from index.html
<click-counter count="5"></click-counter>
<link rel="import" href="clickcounter.html">
results in the following error:
Exception: NoSuchMethodError: method not found: 'whenPolymerReady'
Receiver: Instance of 'JsFunction'
Arguments: [Closure: () => dynamic] (package:polymer/src/loader.dart:115)
Breaking on exception: NoSuchMethodError: method not found: 'whenPolymerReady'
I have used the mechanism all the time in creating any polymer app, but has never seen such exception although I have seen documentation on the web involving Dart https://www.google.com.jm/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CBwQFjAA&url=http%3A%2F%2Fcode.google.com%2Fp%2Fdart%2Fissues%2Fdetail%3Fid%3D19161&ei=MZq8U_nlK42KyASBkYHgCw&usg=AFQjCNHOc6MD-mhzPbDOmg8Hp5NeqVufqQ&bvm=bv.70138588,d.aWw
The documentation suggested that this problem had resolved but it certainly is present in the current polymer I am using.
Each of your components (each file containing a <polymer-element> tag) must import polymer.html.
Make sure your clickcounter.html contains the line:
<link rel="import" href="packages/polymer/polymer.html" />
at the top. (It was breaking change in 0.11).
I'm clueless about these things, but for me I seemed to solve it by moving the following code:
<!-- after the Polymer elements imports -->
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script async src="packages/browser/dart.js"></script>
from the end of the <head>er, to just before the </body>.
Only my index.html now contains these lines. Lastly I also moved my custom element import above core-elements/paper-elements imports.
My dummy application created from the polymer template starts fine, but once I move the clickcounter to another directory, I start getting this error (I have updated references accordingly). My new folder structure is the following:
/lib
/src
/test
clickcounter.dart
clickcounter.html
/web
polytest.html
This is how the modified line looks:
<link rel="import" href="../lib/src/test/clickcounter.html">
I think I found the solution.
The clickcounter.html |imports link rel="import" href="packages/polymer/polymer.html|". In the entry-point file, there is no such import. When a component is imported into the entry-point, it seems that the polymer.html condition is satisfied. In the absence of a component the import has to placed directly in the file.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample app</title>
<!-- <script src="packages/web_components/platform.js"></script>
not necessary anymore with Polymer > 0.14.0 -->
<script src="packages/web_components/dart_support.js"></script>
<link rel="import" href="packages/polymer/polymer.html">
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
<link rel="stylesheet" href="epimss_material_design.css">
</head>
<body>
<h1>Epimss material design</h1>
<p>Hello world from Dart!</p>
<div id="sample_container_id">
</div>
</body>
</html>
After that everything worked fine.
The same problem actually resurfaced in Dart SDK 1.6.0-dev.1.2 and was similarly solved. Still, I cannot say if its a bug or not. It simply works by adding this import. I suppose if a legitimate component is used that imports would allow the removal of the same import from the entry-point file. One of Dart or Dart-polymer expert might be able to explain what actually is happening. Looking forward to the in-depth explanation since this is the first time I have observed this issue.
I just ran into the same issue.
Are you sure your polymer imports are underneath your javascript imports?
<!-- <script src="packages/web_components/platform.js"></script>
not necessary anymore with Polymer 0.14.0 -->
<script src="packages/web_components/dart_support.js"></script>
<!-- import the click-counter -->
<link rel="import" href="clickcounter.html">
instead of:
<!-- import the click-counter -->
<link rel="import" href="clickcounter.html">
<script src="packages/web_components/platform.js"></script>
<script src="packages/web_components/dart_support.js"></script>
I'm not in that development, but it seems like your problem is API or dependencies used in application.
I think your transformer settings is missing the entry page
transformers:
- polymer:
entry_points:
- example/index.html
Otherwise look closely at the output if there is any other warning or error that points to the root causel
I've just had exactly the same issue. It looked like the code stopped working without any change performed by me.
Root cause of the issue was, that there appeared a new version of polymer package.
So you should probably play with dependencies in your pubspec.yaml. I just explicitly changed the version of Polymer to some older one.

Dart Todo Application

I am working through the dart todo sample application. I haven't changed any code but I see lots of squiggles in the editor.
<polymer-element name="simple-router">
<script type="application/dart;component=1"
src="simple_router.dart"></script>
</polymer-element>
The error I'm seeing reads.
Wrong script type, expected
type="application/dart".
I don't understand what this means. When I strip off the ;component=1. It really breaks the application.
This is code that was valid in Polymer about ">= 0.10.5 <0.11.0" but there were several changes.
;component=1 Should be remove from all script tags.
The imports and script tags in the entry page should look like
<html>
<head>
<title>core-ajax-dart</title>
<!-- when the project uses polymer -->
<!-- <script src="packages/web_components/platform.js"></script>
not necessary anymore with Polymer >= 0.14.0 -->
<script src="packages/web_components/dart_support.js"></script>
<!-- import individual polymer elements -->
<link rel='import' href='packages/core_elements/core_ajax_dart.html'>
</head>
<body>
<core-ajax-dart
url="http://gdata.youtube.com/feeds/api/videos/"
params='{"alt":"json", "q":"chrome"}'
handleAs="json"
auto></core-ajax-dart>
<!-- if you have a custom script file that contains a main() method -->
<script type="application/dart" src="core_ajax_dart.dart"></script>
<!-- else if you don't have a custom script file with a main() method
<script type="application/dart">export 'package:polymer/init.dart';</script>
</body>
</html>
see here how to implement a custom main method.
how to implement a main function in polymer apps

loading a web component from a lib subdirectory

When trying to insert a html file for a webcomponent into the views directory in my application library, the web_ui compiler throws the message
FileIOException: Cannot retrieve full path for file 'lib\src\view\entity\base\packages' (OS Error: The system cannot find the file specified.
Is this to be expected? If not, what should I do to fix the error?
Since I don't see your code or project, this is just a hunch. I believe your web component HTML file imports some components the wrong way.
Try the follow this structure:
/lib/src/view/foo/foo.html
/lib/src/view/foo/foo.dart
/lib/src/view/bar/bar.html
/lib/src/view/bar/bar.dart
And inside foo.html:
<!DOCTYPE html>
<html>
<head>
<link rel="components" href="../bar/bar.html" />
</head>
<body>
<element name="x-foo" constructor="FooComponent" extends="div">
<template>
...
</template>
<script type="application/dart" src="foo.dart"></script>
</element>
</body>
</html>
Note that I'm not using packages in foo.html.

When is the removed lifecycle method called for Dart web components?

Latest edit:
This is an open issue in web-ui: https://github.com/dart-lang/web-ui/issues/245
Previously:
I'm trying to figure out how to get removed() from the web component lifecycle methods to be called. Looking through the generated code for my below example, I see there's a call to autogenerated.dispatch(); after replaceElement() which I hoped would be what calls removed(), but I don't see my print statement output.
Maybe related: I glanced through the spec trying to understand what the output of build.dart is doing for the lifecycle methods. Perhaps the spec is out of date? I still don't see composeChildren() listed in the instantiation section of the spec (which is mentioned in this web-ui issue comment) even though composeChildren() gets called in the autogenerated code from build.dart.
The reason behind this question is my interest in a Dart webapp able to load and unload web components within a single parent html file programmatically (via the instantiation instructions in the spec), instead of having to declare web components in the html. I'm running with web_ui-0.2.11. Thanks!
webcomponent:
<!DOCTYPE html>
<html><body>
<element name="x-lifecycle-test" constructor="LifecycleTest" extends="div">
<template> {{foo}} </template>
<script type="application/dart">
import 'dart:html';
import 'package:web_ui/web_ui.dart';
var foo = "testing lifecycle methods";
class LifecycleTest extends WebComponent{
inserted() => print("inserted");
removed() => print("removed");
}
</script>
</element>
</body></html>
Parent html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"><title>Lifecycle</title>
<link rel="components" href="lifecycle_test.html">
</head>
<body>
<div>
<button on-click="replaceElement()">replace element</button>
</div>
<div id='holder'>
<x-lifecycle-test></x-lifecycle-test>
</div>
<script type="application/dart">
import 'dart:html';
void replaceElement() {
query('#holder').replaceWith(new DivElement()
..id = 'holder'
..text = 'replaced');
}
main() {}
</script>
<script type='text/javascript' src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/client/dart.js"></script>
</body>
</html>
Adding an answer here for completeness: web components are used in Dart using Polymer. When an instance of a custom element is removed from the DOM, the leftView life cycle method triggers. You can read more about this at https://www.dartlang.org/docs/tutorials/polymer-intro/#life-cycle-methods.

How can I link to an external Dart library containing the constructor for my web component?

I've been following the Dart web-ui codelab. When I embed dart source code inside a web component .html file, I'm not getting any static analysis or autocomplete support in the Dart Editor (there's an open bug for this http://code.google.com/p/dart/issues/detail?id=7449 ). Hence, I'm looking for a temporary workaround by using the src attribute.
According to the spec, the src attribute is supported for web components in Dart:
https://www.dartlang.org/articles/dart-web-components/spec.html#behavior. I tried linking to an external Dart library: given a foo.html web component for
<element name="x-foo-component" constructor="FooComponent" extends="div">
I'd like to link to a separate foo_embed.dart file in the same directory as my web component, which defines FooComponent, by adding:
<script type="application/dart" src="foo_embed.dart"></script>
within foo.html. Following the spec's suggestions, foo_embed.dart needs to be a Dart library, and would contain:
library foo_embed;
import 'package:web_ui/web_ui.dart';
class FooComponent extends WebComponent {
...
}
When I try this, running build.dart (from these instructions http://www.dartlang.org/articles/dart-web-components/tools.html) ends up only putting foo_embed.dart in out/ and there's no out/foo.html.dart generated for importing in application.dart.
As expected, pasting the contents of foo_embed.dart as an inline script inside foo.html directly (as done in the codelab) works with build.dart, and I can launch my webapp in Dartium, so I don't seem to have any other syntax problems in my project.
Do I probably have a simple syntax mistake somewhere? Or is this a temporary limitation of the Dart web components compiler? Thanks.
I can't reproduce your problem.
This works for me:
lib/foo.dart
library foo;
import 'package:web_ui/web_ui.dart';
class FooComponent extends WebComponent {
var foo = 'asddfg';
}
lib/foo.html
<element name="x-foo" constructor="FooComponent" extends="div">
<template>
<input value="{{ foo }}" />
</template>
<script type="application/dart" src="foo.dart"></script>
</element>
example/test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="components" href="packages/foo/foo.html" />
</head>
<body>
<x-foo></x-foo>
<script type="application/dart">main() {}</script>
<script type="text/javascript" src="https://dart.googlecode.com/svn/branches/bleeding_edge/dart/client/dart.js"></script>
</body>
</html>
Then I open up Dartium and go to .../example/out/test.html and I see an input with the data bound to it properly.

Resources