How to Use Dart Route API - dart

I have created a sample app to test the Dart Route API. I have the following code:
urls.dart
library urls;
import 'package:route/url_pattern.dart';
final homeUrl = new UrlPattern(r'/');
final otherScreenUrl = new UrlPattern(r'/other_screen/');
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<div id="sample_container_id">
<p id="sample_text_id"></p>
</div>
<script type="application/dart" src="main.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main.dart
import 'dart:html';
import 'package:route/client.dart';
import 'urls.dart';
void main() {
var router = new Router()
..addHandler(homeUrl, _showHome)
..addHandler(otherScreenUrl, _showOtherScreen)
..listen();
querySelector("#sample_text_id")
..text = "Click me!"
..onClick.listen(_gotoOtherScreen);
}
_gotoOtherScreen(MouseEvent event) {
// I am trying to navigate to the "other screen" by using history.pushState here
window.history.pushState({'url' : otherScreenUrl}, "other screen", otherScreenUrl);
}
_showHome(String path) {
querySelector("#other_element")
..remove();
}
_showOtherScreen(String path) {
querySelector("#sample_container_id")
..append(new SpanElement()
..innerHtml = "now in other screen"
..id = "other_element");
}
I am getting the following errors when running the app and then clicking on the <p> tag:
Breaking on exception: Illegal argument(s): No handler found for
/test/web/main.html
Exception: Illegal argument(s): No handler found for
/test/web/main.html Router._getUrl (package:route/client.dart:53:7)
Router.handle (package:route/client.dart:71:22)
Router.listen. (package:route/client.dart:102:15)
Breaking on exception: type 'UrlPattern' is not a subtype of type
'String' of 'url'.
Exception: type 'UrlPattern' is not a subtype of type 'String' of
'url'. _gotoOtherScreen
(http://127.0.0.1:3030/test/web/main.dart:18:27)
How is the Route API supposed to be used? What am I doing wrong?

The following is the updated code that solves the above issues:
urls.dart
library urls;
import 'package:route/url_pattern.dart';
final homeUrl = new UrlPattern(r'(.*)/');
final homeUrlWithFile = new UrlPattern(r'(.*)/main.html');
final otherScreenUrl = new UrlPattern(r'(.*)/other_screen');
main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<div id="sample_container_id">
click me!!
</div>
<script type="application/dart" src="main.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main.dart
import 'dart:html';
import 'package:route/client.dart';
import 'urls.dart';
void main() {
var router = new Router()
..addHandler(homeUrl, _showHome)
..addHandler(homeUrlWithFile, _showHome)
..addHandler(otherScreenUrl, _showOtherScreen)
..listen();
}
_showHome(String path) {
var e = querySelector("#other_element");
if (e != null) e.remove();
}
_showOtherScreen(String path) {
querySelector("#sample_container_id")
..append(new SpanElement()
..innerHtml = "now in other screen"
..id = "other_element");
}

Related

Communicating with a shared worker in Dart

I'm trying to communicate with a shared worker from Dart, but I haven't had any success and I've tried everything I can think of.
As a test, I'm just trying to get a basic worker which simply responds with whatever it is sent working.
Starting from the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="scaffolded-by" content="https://github.com/google/stagehand">
<title>wtf</title>
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart" type="application/dart"></script>
<script defer src="packages/browser/dart.js"></script>
<!-- <script defer src="test.js"></script> -->
</head>
<body>
<div id="output"></div>
</body>
</html>
JavaScript worker (worker.js):
onconnect = function(e) {
var port = e.ports[0];
port.onmessage = function(e) {
port.postMessage("Worker received message: " + e.data);
}
}
The Dart code (main.dart):
import 'dart:html';
import 'dart:async';
void main() async {
var myWorker = new SharedWorker("worker.js");
myWorker.port.onMessage.listen((msg) {
print("Worker says: " + msg);
});
new Timer.periodic(const Duration(seconds: 1), (timer) {
myWorker.port.postMessage("Hello, world");
});
}
The writer does get invoked every second, and I've verified that the shared worker does run (with chrome://inspect).
To narrow the problem down I threw together a JavaScript version of the Dart code (in test.js) which works as expected. If you comment out the contents of main() and uncomment the reference in the HTML to test.js it works. Contents of test.js:
var myWorker = new SharedWorker("worker.js");
myWorker.port.onmessage = function(e) {
console.log("Worker says: " + e.data);
}
setInterval(function() {
myWorker.port.postMessage("Hello, world");
}, 1000);
However, when using the Dart version nothing is written to the console. There are no errors at either compile-time or run-time. It just silently fails.
Any help would be greatly appreciated. I'm probably missing something stupid, but I've been stuck on this for longer than I care to admit…
Since the worker is a SharedWorker, you should call the method:
myWorker.port.start();
just after attach the onMessage listener, (documentation at MDN):
If the onmessage event is attached using addEventListener, the port is manually started using its start() method
Also, at the listener, the parameter msg is a MessageEvent and the text can be retrieved by accessing data property (same as your JS code):
print("Worker says: " + msg.data);
Follow the whole code with the changes:
import 'dart:html';
import 'dart:async';
void main() async {
var myWorker = new SharedWorker("worker.js");
myWorker.port.onMessage.listen((msg) {
print("Worker says: " + msg.data);
});
myWorker.port.start();
new Timer.periodic(const Duration(seconds: 1), (timer) {
myWorker.port.postMessage("Hello, world");
});
}
tested with Dart 1.19.1

Using Skrollr with Dart

I'm trying to implement some scroll based animation in my Dart web application using Skrollr.js. So far I have the following in main():
main() {
ScriptElement script = new ScriptElement()
..type = 'application/javascript'
..src = 'skrollr.min.js';
document.body.children.add(script);
ScriptElement script2 = new ScriptElement()
..type = 'application/javascript'
..innerHtml = 'var s = skrollr.init({forceHeight: false});';
document.body.children.add(script2);
js.context.callMethod('skrollr', ['init({forceHeight: false})']);
}
For some reason I'm getting the following errors when run:
Uncaught ReferenceError: skrollr is not defined and
Exception: NoSuchMethodError: method not found: 'skrollr'
skroller.min.js has been placed in the app next to index.html so I'm looking for help on what is wrong here.
Also if the is a pure Dart alternative for scroll based animations I'd be happy to know of that as well.
Thanks in advance.
just use:
import 'dart:js';
void main() {
void keyframe(element, name, direction) {
}
context['skrollr'].callMethod('init', [{'keyframe': keyframe}]);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>skrollr</title>
<script type="text/javascript" src="skrollr.min.js"></script>
</head>
<body>
<script type="application/dart" src="main.dart"></script>
<script data-pub-inline src="packages/browser/dart.js"></script>
</body>
</html>
this works. no problem with it.

Polymer Dart $[] selector in an autobinding model

Since polymer-body has been removed, we need to use an auto-binded template to use polymer binding features outside of a PolymerElement:
<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>
<script src="packages/web_components/dart_support.js"></script>
<link rel="import" href="packages/polymer/polymer.html">
<script src="packages/browser/dart.js"></script>
</head>
<body>
<template is="auto-binding-dart">
<div>Say something: <input value="{{value}}"></div>
<div>You said: {{value}}</div>
<button id="mybutton" on-tap="{{buttonTap}}">Tap me!</button>
</template>
<script type="application/dart">
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:template_binding/template_binding.dart';
main() {
initPolymer().run(() {
Polymer.onReady.then((_) {
var template = document.querySelector('template');
templateBind(template).model = new MyModel();
});
});
}
class MyModel extends Observable {
//$['mybutton'] wont works there
#observable String value = 'something';
buttonTap() => print('tap!');
}
</script>
</body>
</html>
Unfortunately, the whole model now extends Observable, every binding seems to work, but the PolymerElement array selector $['foo'] cant be used anymore...
Is there any easy way to implement this $['id'] selector into an Observable model?
I would suggest to use a normal Polymer element instead of auto-binding-dart.
Then you don't have to care about differences and you need no 'main'.
I always start a Polymer project with an <app-element> Polymer element that acts as main() and container for the entire app.
I also would suggest to not use inline code.
As far as I know it has some limitations especially debugging is not supported (might be fixed already, I don't know because I never use it).
To make $ work you need a small and simple workaround;
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:template_binding/template_binding.dart';
Map<String, dynamic> $; // we define our own '$'
main() {
initPolymer().run(() {
Polymer.onReady.then((_) {
var template = document.querySelector('template') as Polymer;
$ = template.$; // we assign template.$ to our own '$' so we can omit the 'template' part
templateBind(template).model = new MyModel();
});
});
}
class MyModel extends Observable {
//$['mybutton'] wont work there - it can't because this is outside of a method
#observable String value = 'something';
buttonTap() {
print($['mybutton'].id); // here it works
print('tap!');
}
}

Dynamically add a web component to a div

I started with the generating click-counter example. I made the click-counter into a library which I then imported into my main file. The click-counter component can be added manually by putting the appropriate HTML into the web page before running the program. However, I've been unable to find a way to dynamically add the click-counter web component to a div. My attempts have either ended in "Aw, snap!" errors or simply with nothing happening.
The click-counter (xclickcounter.dart):
library clickcounter;
import 'package:web_ui/web_ui.dart';
class CounterComponent extends WebComponent {
int count = 0;
void increment() {
count++;
}
}
The main HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample app</title>
<link rel="stylesheet" href="test1.css">
<!-- import the click-counter -->
<link rel="components" href="xclickcounter.html">
</head>
<body>
<h1>Test1</h1>
<p>Hello world from Dart!</p>
<div id="sample_container_id">
<div is="x-click-counter" id="click_counter" count="{{startingCount}}"></div>
</div>
<script type="application/dart" src="test1.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main file:
import 'dart:html';
import 'package:web_ui/web_ui.dart';
import 'xclickcounter.dart';
// initial value for click-counter
int startingCount = 5;
void main() {
// no error for adding an empty button
var button = new ButtonElement();
query('#sample_container_id').append(button);
// doesn't work (gives "Aw, snap!" in Dartium)
query('#sample_container_id').append(new CounterComponent());
// Nothing happens with this code. Nothing appears.
// But I promise this same thing was giving Aw, Snap
// for a very similar program
final newComponentHtml = '<div is="x-click-counter"></div>';
query('#sample_container_id').appendHtml(newComponentHtml);
}
I tried added an empty constructor to click-counter but it still crashes.
I had the same issue.
See the example (not mine) at https://github.com/dart-lang/web-ui/blob/master/test/data/input/component_created_in_code_test.html and let me know if it works for you.
TL;DR:
void main() {
var element = query('#sample_container_id');
appendComponentToElement(element, new CounterComponent() );
}
void appendComponentToElement(Element element, WebComponent component) {
component.host = new DivElement();
var lifecycleCaller = new ComponentItem(component)..create();
element.append(component.host);
lifecycleCaller.insert();
}
There's more info at my web-ui#dartlang.org post: https://groups.google.com/a/dartlang.org/d/topic/web-ui/hACXh69UqG4/discussion
Hope that helps.

How do I dynamically load HTML and insert into my web page with Dart?

How do I dynamically load a snippet of HTML and insert it into my web page? I am using Dart.
Glad you asked! Using Dart for this task isn't much different than JavaScript, except you get typing, code completion, and a slick editing experience.
First, create the snippet.html:
<p>This is the snippet</p>
Next, create the application. Notice the use of XMLHttpRequest to request the snippet. Also, use new Element.html(string) to create a block of HTML from a string.
import 'dart:html';
void main() {
var div = querySelector('#insert-here');
HttpRequest.getString("snippet.html").then((resp) {
div.append(new Element.html(resp));
});
}
Finally, here's the host HTML page:
<!DOCTYPE html>
<html>
<head>
<title>dynamicdiv</title>
</head>
<body>
<h1>dynamicdiv</h1>
<div id="insert-here"></div>
<script type="application/dart" src="dynamicdiv.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
main.dart:
import 'dart:html';
DivElement div = querySelector('div');
main() async {
String template = await HttpRequest.getString("template.html");
div.setInnerHtml(template, treeSanitizer: NodeTreeSanitizer.trusted);
}
template.html:
<h1>Hello world.</h1>
Check my bird... <em>it flies</em> !
<img src="https://www.dartlang.org/logos/dart-bird.svg">
For the full example, that runs out of the box, see:
https://gist.github.com/kasperpeulen/536b021ac1cf397d4e6d
Note that you need 1.12 to get NodeTreeSanitizer.trusted working.
You can try this example.
https://jsfiddle.net/kofwe39d/ (JS compiled from Dart source code.)
web/main.dart
import 'dart:async';
import 'dart:html';
import 'package:virtual_dom/components/component.dart';
import 'package:virtual_dom/features/state.dart';
import 'package:virtual_dom/helpers/h.dart';
import 'package:virtual_dom/helpers/mount.dart';
import 'package:virtual_dom/helpers/styles.dart';
import 'package:virtual_dom/helpers/vhtml.dart';
void main() {
final app = document.getElementById('app')!;
mount(app, _App());
}
class _App extends Component {
#override
Object render() {
final timer = State.get('timer', () => 3);
final setTimer = State.set<int>('timer');
if (timer > 0) {
Timer(Duration(seconds: 1), () {
setTimer(timer - 1);
});
}
final html = timer > 0
? ''
: '''
Hello, <strong>World!</strong>
''';
final style = styles({'padding': '6px'});
return h('div', {
'style': style
}, [
if (timer > 0) '$timer sec',
h('p', 'Your html:'),
vHtml('div', html),
]);
}
}
web/index.html
<!DOCTYPE html>
<html style="height: 100%;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example application</title>
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="styles.css">
<script defer src="main.dart.js"></script>
</head>
<body style="height: 100%; font-family: Verdana,sans-serif; font-size:15px; line-height:1.5">
<div id="app" style="height: 100%;"></div>
</body>
</html>

Resources