I want to use the Smoke package and it worked (without using a transformer just in debug mode) on the server side.
On the client side Smoke is already used by Polymer and when I use a method like assert(sk.isSubclassOf(type, Message)); it fails because internal it checks against the _parents collection and this contains only Polymer elements used on my page but none of my other (pure Dart) classes.
How do I initialize Smoke so it recognizes my other classes too.
I got it working using a custom main() for my Polymer entry page.
import 'package:smoke/mirrors.dart' as skm;
import 'package:polymer/polymer.dart';
void main() {
skm.useMirrors(); // worked on the server side without calling this method
initPolymer().run(() {});
}
Related
I'm writing a discord bot using the nyxx library and want use dynamic file import for load command info and handler. But, after 5 hours of searching with Google, I didn't find anything to help me do that.
In Node.js, I can use require() or import() for it: Does the dart have something like that?
A small code snippet, showing what I want do:
this.commands = new Collection();
fs.readdirSync('./src/commands').filter(( f ) => f.endsWith( '.js' )).forEach((file) => {
const command = require(`../commands/${file}`);
this.commands.set( command.info.name, command );
});
Is it possible to do this or not? (I don't like to write many imports for commands and register it in lib.)
You can in theory use Isolate.spawnUri to spawn external Dart programs to run in its own Isolate instances that can then communicate back to the main program using SendPort.
It does, however, come with some limitations. E.g. it is very limited what types of objects you can send though SendPort when using spawnUri since the two programs does not share any type information (compared to Isolate.spawn which does allow you to send your own custom types). The documented types you can send can be found here:
Null
bool
int
double
String
List or Map (whose elements are any of these)
TransferableTypedData
SendPort
Capability
https://api.dart.dev/stable/2.17.6/dart-isolate/SendPort/send.html
But it does allow us to make some kind of protocol and you can create some helper class around this to handle the conversion of a known object structure into e.g. Map<String, Object>.
A small example that works with Dart VM would be:
Your command implemented as: command.dart
import 'dart:isolate';
void main(List<String> arguments, Map<String, Object> message) {
final userName = message['username'] as String;
final sendPort = message['port'] as SendPort;
sendPort.send('Hi $userName. '
'You got a message from my external command program!');
}
Your server that calls your command: server.dart
import 'dart:isolate';
void main() {
final recievePort = ReceivePort();
recievePort.listen((message) {
print('Got the following message: $message');
recievePort.close();
});
Isolate.spawnUri(Uri.file('command.dart'), [], {
'username': 'julemand101',
'port': recievePort.sendPort,
});
}
If running this with: dart server.dart you, hopefully, get:
Got the following message: Hi julemand101. You got a message from my external command program!
If you want to compile your application, you can do so by doing the following. You need to compile the command.dart, since a compiled Dart program does not understand how to read Dart code.
dart compile exe server.dart
dart compile aot-snapshot command.dart
You should here change Uri.file('command.dart') to Uri.file('command.aot') since the file-extension for aot-snapshot are .aot.
If everything works, you should be able to see:
> .\server.exe
Got the following message: Hi julemand101. You got a message from my external command program!
I am planing to use semantic ui modal has anyone any idea, how to interoperate with dart?
Use the js package to interoperate. First, add the package as a dependency. Then, wrap the JavaScript that you want to use from Dart. Here's an example allowing you to use jQuery's $(...).addClass(...) in Dart:
#JS()
library jquery;
import 'package:js/js.dart';
// Calls invoke JavaScript `JSON.stringify(obj)`.
#JS("\$")
external ElementSet $(String selector);
#JS()
class ElementSet {
external addClass(String className);
}
If you import this file, you can now do:
$('#output').addClass("red");
That example is, of course, quite useless — Dart already allows you to modify HTML classes with better readability and flexibility (e.g. querySelector('#output').classes.add("red")).
But in your case, it starts to make sense. You would implement modal() and go from there.
(I would give you an example of how to implement modal, but I wasn't able to install semantic ui on my workstation for 10+ minutes and then I gave up. So I used the jQuery.addClass example instead.)
It's not that easy. There are two or three pub packages available but they are outdated and incomplete.
I did it this way in Dart 2 (AngularDart 5):
import 'dart:js';
// somewhere in the component:
context
.callMethod(r'$', [modalSelector])
.callMethod('modal', [new JsObject.jsify({
'onApprove': new JsFunction.withThis((element){
// do something on approve
})
})])
.callMethod('modal', ['show']);
This Dart code is equivalent to this Javascript code:
$(modalSelector).modal({
'onApprove': function(element){
// do something on approve
})
.modal('show');
As you may see, you have to call the jQuery framework through the JS module.
Is it possible to run transformer on a command line application before running it?
For example, if I have a class that mixes in Observable class. And I would like to transform it so that dirtCheck is transformed into ChangeNotifier.
holder.dart
class Member extends Object with ChangeNotifier {
#observable
String name = "";
}
class Holder extends Object with ChangeNotifier {
Holder() {
}
#observable
Member member = new Member();
}
pubspec.yml
transformers:
- observe:
files:
- bin/models/holder.dart
If I run this application from IntelliJ IDE, it doesn't seem to run the transformer on it before executing main.dart.
Thanks.
Transfomers are not applied to command line apps. Only code that is served using pub serve or pub build runs and applies transformers. Your code should run on the server/command line as is. There is no need to run transformers.
Transformers are used for observe to replace dart:mirrors access by generated code to prevent code bloat for dart2js-generated JS but this is no issue on the command line.
I've tried to bind a custom event handler to a WebComponent that has an EventStreamProvider exposed via a getter, but it comes back with "Class 'DivElement' has no instance getter 'onMainAction'.".
Trimmed down component .dart code...
import 'dart:html';
import 'dart:async';
import 'package:web_ui/web_ui.dart';
class SegmentedButtonsListComponent extends WebComponent {
static const EventStreamProvider<CustomEvent> mainActionEvent = const EventStreamProvider<CustomEvent>("MainActionEvent");
Stream<CustomEvent> get onMainAction => mainActionEvent.forTarget(this);
}
Trimmed usage of component…
<x-segmented-buttons-list id="segmented-buttons-list" on-main-action="eventHandler($event)"></x-segmented-buttons-list>
Trimmed code from main.dart…
import 'dart:html';
import 'dart:async';
import 'package:web_ui/web_ui.dart';
const EventStreamProvider<CustomEvent> mainActionEvent = const EventStreamProvider<CustomEvent>("MainActionEvent");
void eventHandler(CustomEvent event) {
print("""
Yabba Dabba Doo!
Type: ${event.type}
Detail: ${event.detail}
""");
}
void main() {
mainActionEvent.forTarget(query('#segmented-buttons-list')).listen(eventHandler);
}
The "MainActionEvent" custom events are being dispatched by components instantiated within this "list" component.
As you can see from the above example I can catch the events if I create an EventStreamProvider in main.dart and target the component, that works fine (but by-passes the Stream getter in the component).
It would be great though if I could dispense with the EventStreamProvider in main.dart and simply bind to the onMainEvent getter on the component.
Is that possible?
Update 2013-05-05:
Siggi explains below that at present it is not possible to do this, but there is a way to reference the component's CustomEventProvider's getter via the element's xtag.
I found that I had to use a Timer to query the DOM after main() has completed because xtags aren't populated until the main() event loop has finished.
void postMainSetup() {
query('#segmented-buttons-list').xtag.onMainAction.listen(eventHandler);
}
void main() {
Timer.run(postMainSetup);
}
With the above setup a new CustomEventProvider isn't needed to monitor the component.
Good question!
I see a couple parts to this question:
using custom events directly on a component: Currently web_ui uses different objects to represent your component and the actual dom element it represents. In the future, we plan to extend directly from "DivElement" instead of "WebComponent" and that will allow you to do what you wrote.
Meanwhile, you'll have to be more explicit when you want to use the host or shadow root of your component. In your example, it seems like you want to attach the event to the host, so you would need to write something more like this:
Stream<CustomEvent> get onMainAction => mainActionEvent.forTarget(this.host);
using 'on-someting-foo' syntax in a component: you probably found a bug/missing feature =). Currently we treat attributes in a special way and bind their values to fields of a component if we identify that the target was corresponds to a component. We do this for value bindings, but not yet for binding custom events. A workaround before this feature is added, would be to query for your element and attach the event by hand:
query('#host-node').xtag.onMainAction.listen(...);
I created a bare-bones datagrid using web-ui for testing and had it working just fine. Then I decided to try to declare it as a component. I changed around the library references and now it is giving me the above error when I try to run the application. You can see my file structure below. The reason I am getting the "ambiguous reference" message when I try to run it is that when I went into the auto-generated DataGrid.dart file in the out directory, it had the following declaration
import 'DataGrid.dart';
...
import '../DataGrid.dart';
I am confused as to why the generated code imports them both. One thing that I considered is that it could be because the DataGridPage.html file instantiates my DataGrid component and my DataGridPage.dart file imports DataGrid.dart so that it can have references to DataGridColumn (it needs to set the columns for the DataGrid). In DataGridPage.dart, I also attach to certain DataGrid events such as SortColumnChanged and SelectionChanged so I need to request a copy of my DataGrid instance in DataGridPage.dart (I don't think there is a way to attach to events from the web component instantiation in DataGridPage.html).
Any ideas about what I am doing wrong?
Here is my file structure:
DataGrid.dart
--------------------------------------------
library datagrid;
...
part 'DataGridColumn.dart';
part 'DataGridRow.dart';
class DataGrid extends WebComponent{...}
DataGridRow.dart
--------------------------------------------
part of datagrid;
class DataGridRow {...}
DataGridColumn.dart
--------------------------------------------
part of datagrid;
class DataGridColumn {...}
DataGrid.html
--------------------------------------------
[contains the component declaration UI]
DataGridPage.html
-----------------------------------------
...
<div is="s-datagrid" id="myDataGrid" ItemsSource="{{app.Assets}}" Columns="{{app.Columns}}"></div>
...
DataGridPage.dart
--------------------------------------------
import 'DataGrid.dart';
import 'Asset.dart';
void main() {
}
DataGridApp _app;
DataGridApp get app {
if (_app == null) {
_app = new DataGridApp();
}
return _app;
}
class DataGridApp{
//provides ItemsSource and DataGridColumn data
}
jmesserly has answered this on the github site. He said that you need to remove the component import in your main dart file. So in my example I would remove the import 'DataGrid.dart' statement from the DataGridPage.dart. The IDE will give you a warning but you can ignore it because it will actually be run from the out folder.
GitHub Web-UI Issue 342