I'm trying to extend PaperDialog so that I can style it. I'm attempting to use method 3 from this solution, but with Dart instead of JS. Here's my component.
<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="packages/paper_elements/paper_dialog.html">
<polymer-element name="hc-dialog" extends="paper-dialog" noscript>
<template>
<link href="hc-dialog.css" rel="stylesheet" type="text/css" />
<shadow></shadow>
</template>
</polymer-element>
The component appears to render correctly into the DOM - and I can verify that it functions correctly by adding opened="true" to the component - this renders great for example:
<hc-dialog opened="true" closeSelector="[dismissive]" transition="paper-dialog-transition-bottom">
<div layout horizontal>
<span flex></span>
<paper-button raised dismissive>Done</paper-button>
</div>
</hc-dialog>
But I don't want it auto-showing, and the issue comes when trying to find a way to call toggle() on this component via Dart. In the solution linked above (working JS Fiddle), it's called via JS:
<script>
Polymer('x-dialog-3', {
toggle: function() {
this.$.dialog3.toggle();
}
});
</script>
However if I try to achieve the same thing in dart, I'm unable to retrieve a component that has the toggle() method on it:
shadowRoot.querySelector('hc-dialog').toggle();
results in Object.noSuchMethod. Inspecting the returned object via reflection makes that clear:
var he = shadowRoot.querySelector('hc-dialog');
var cm = reflect(he).type;
while (cm != null) {
print(cm);
cm = cm.superclass;
}
gives:
ClassMirror on 'HtmlElement' (:1)
ClassMirror on 'Element' (:1)
ClassMirror on 'Node' (:1)
ClassMirror on 'EventTarget' (:1)
ClassMirror on 'NativeFieldWrapperClass2' (:1)
ClassMirror on 'Object' (:1)
==> My Dialog is not a PaperDialog/CoreOverlay, which is why I can't call toggle() on it.
What's wrong with this approach? How do I go about getting something I can call toggle() on?
Polymer.dart core- and paper-elements are just wrappers around Polymer.js elements. Extending is not supported for these kind of elements becaus a Dart class can't extend a JS class.
Related
I am using beta3 of Vaadin 10 and I have a html-file bound to a Component (#HtmlImport), which contains a <dom-repeat> inside of which I have a paper-radio-group. I want the paper-radio-group#selected-property to be bound two way to my model, so that when a user selects a different radio-button, it's value will be written back to the model. Unfortunately, for me it works only as a one way model, as the java-side setter setAOrBProperty() is never called. Can someone give me a hint what I need to do to have the new value written to the server?
<link rel="import" href="./bower_components/polymer/polymer-element.html">
<link rel="import" href="bower_components/paper-radio-button/paper-radio-button.html">
<link rel="import" href="bower_components/paper-radio-group/paper-radio-group.html">
<dom-module id=“dmmdl”>
<template>
<div>
<dom-repeat items=“[[myListOfSomething]]”>
<div>
<paper-radio-group selected="{{item.aOrBProperty}}” allow-empty-selection>
<paper-radio-button name=“a”>A</paper-radio-button>
<paper-radio-button name=“b”>B</paper-radio-button>
</paper-radio-group>
</div>
</template>
</div>
</template>
<script>
class BooksGridElement extends Polymer.Element {
static get is() {
return 'books-grid'
}
// only for testing !!
// ready() {
// super.ready();
// this.books = results;
// }
}
customElements.define(BooksGridElement.is, BooksGridElement);
</script>
</dom-module>
I suspect this is caused by a security feature of Flow. Arbitrary model value changes from the client are not accepted for security reasons. Instead, changes are only allowed for properties that are used in two-way template bindings (i.e. {{propertyName}}) or explicitly annotated with #AllowClientUpdates on the corresponding Java getter.
The logic that looks for {{propertyName}} doesn't have any specific knowledge about the inner workings of <dom-repeat>, so it cannot know that {{item.aOrBProperty}} corresponds to myListOfSomething[*].aOrBProperty.
If my assumption is correct, you could fix this case by adding #AllowClientUpdates to the getAOrBProperty() method in your model interface.
I'm trying to bind an object from an Angular controlled element to a Polymer element in Dart.
The object to bind:
class Person {
String name;
String surname;
Person(this.name, this.surname);
}
The polymer element template:
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="person-element">
<template>
<style>
.label {font-weight: bold;}
</style>
<p>
<span class="label">Name: </span>{{person.name}}
<span class="label">Surname: </span>{{person.surname}}
</p>
</template>
<script type="application/dart" src="person_element.dart"></script>
</polymer-element>
The polymer element code:
import 'package:polymer/polymer.dart';
import 'person.dart';
#CustomTag('person-element')
class PersonElement extends PolymerElement {
#published Person person;
PersonElement.created() : super.created();
}
In Angular I've created a controller and a module:
#Controller(
selector: '[person-container]',
publishAs: 'ctrl')
class PersonController {
List<Person> persons = [new Person('John','Smith'), new Person('Mario','Rossi')];
}
class PersonModule extends Module {
PersonModule() {
bind(PersonController);
}
}
The first solution tried is using the angular_node_bind package:
<div person-container ng-cloak>
<h2>Person elements</h2>
<div ng-repeat="person in ctrl.persons">
<div>{{person.name}}</div>
<person-element person="[[person]]"></person-element>
</div>
</div>
When I run the application in Dartium I get this error:
Exception: type 'String' is not a subtype of type 'Person' of 'value'. (http://localhost:8080/person_element.dart:6)
I've also tried to modify the attribute instantiation in the html code in this way:
<person-element person=[[person]]></person-element>
But I get the same exception.
The angular_node_bind package supports the object binding?
The second solution is using the new binding features of Angular 0.14.0 and binding the polymer element in this way:
With this solution I don't get any exception, the element is visualized but the fields are empty and the person instance null.
The complete example is here: https://github.com/fedy2/dart-angular-polymer-object-data-binding
The new version of AngularDart (0.14.0) has a support for Polymer-Dart binding (http://blog.angulardart.org).
At the moment there can be some problems with different versions:
Pub get failed, [1] Resolving dependencies... Incompatible version constraints on code_transformers
You can find examples at
https://github.com/angular/angular.dart/pull/1461/files
https://github.com/angular/angular.dart/tree/master/example/web
https://github.com/angular/angular.dart/blob/master/example/web/paper.html
https://github.com/angular/angular.dart/blob/master/example/web/paper.dart
https://github.com/angular/angular.dart/blob/master/example/web/paper_radio_group.html
https://github.com/angular/angular.dart/blob/master/example/web/paper_radio_group.dart
also have a look at the same files in the sept15-prg branch.
the new syntax seems to be like
<person-element bind-person="person"></person-element>
It is possible that the released Angular version doesn't yet support some things used by this examples.
I have been trying to extend the paper-item element from the paper_elements package. I do things as I have done when extending my own elements, but that fails.
<link rel="import" href="../../packages/polymer/polymer.html">
<link rel="import" href="../../packages/paper_elements/paper_item.html">
<polymer-element name="x-item" extends="paper-item">
...
</polymer-element>
#CustomTag('x-item')
class XItem extends PaperItem {
XItem.created() : super.created();
}
I get no error message, and no Polymer Element is initialised, with a blank part of the page where ever I've put a Polymer element.
I try using the same method I've used to extend a builtin HTML element like button or div. That also fails.
<link rel="import" href="../../packages/polymer/polymer.html">
<link rel="import" href="../../packages/paper_elements/paper_item.html">
<polymer-element name="x-item" extends="paper-item">
...
</polymer-element>
#CustomTag('x-item')
class XItem extends PaperItem with Polymer, Observable {
XItem.created() : super.created() {
super.polymerCreated();
}
}
And I get
Breaking on exception: NotSupportedError: Registration failed for type 'x-item'. The tag name specified in 'extends' is a custom element name. Use inheritance instead.
If I remove the extends part of the polymer template definition, again I get nothing. Where the Polymer elements in the page have been placed, there is nothing but blankness.
The previous error still happens if I import the actual JS version polymer-item.html via
<link rel="import" href="../../packages/paper_elements/src/paper-item/paper-item.html">
though I still have to extend PaperItem with Polymer and Observable, using the super.polymerCreated(); to generate that error.
I know that the Polymer Dart Team did some trickery to get the underlying paper-elements, which are written in JS, to work almost like they are Polymer Dart elements. I guess this is what's causing the problems. My question is how do I overcome this, so I can extend a paper-element in Dart?
UPDATE - A bug has been submitted https://code.google.com/p/dart/issues/detail?id=20388
I tried it and it also didn't work for me.
I'm pretty sure this is a bug/missing feature with the Dart wrapper for the Polymer.js elements used in paper-elements/core-elements.
You haven't added the HTML of your element.
Does your extending elements template contain a <shadow></shadow> element?
<polymer-element name="x-item" extends="paper-item">
<template>
<shadow></shadow>
</template>
</polymer-element>
I'm working on my first Dart app, having completed the Game of Darts tutorials. I am trying to create a semantically named top-menu element that will eventually display a list of navigation menu tabs at the top of my page. My Dart app is able to recognize my custom element and calls the associated constructor.
However, I am getting a null reference when trying to query for the UL element within my custom element. I need the UL reference in order to dynamically load my LI elements into the menu.
Question 1:
Should the element be visible in the DOM at the point where the constructor is running?
Question 2:
If it is not yet visible, is there a Dart event I can use to trigger loading of the LI elements after the custom element has been completely loaded into the DOM?
Thanks in advance! For reference, here is the source of my custom element:
topmenu-element.html
<!DOCTYPE html>
<html>
<body>
<element name="top-menu" constructor="TopMenu" extends="div">
<template>
<div>
Top Menu
<ul id="top-menu-list"></ul>
</div>
</template>
<script type="application/dart" src="topmenu-element.dart"></script>
</element>
</body>
</html>
topmenu-element.dart
import 'package:web_ui/web_ui.dart';
import 'dart:html';
class TopMenu extends WebComponent {
List menuItems = ['Session', 'Authentication Services', 'Vehicle Services', 'Subscriber Services', 'Data Services'];
void populateMenu() {
UListElement menuList = query('#top-menu-list');
LIElement newMenuItem = new LIElement();
newMenuItem.text = menuItems[0];
menuList.children.add(newMenuItem);
}
TopMenu() {
// populateMenu();
}
}
I can't speak specifically about the DOM visibility in a constructor with the query method as I'm truthfully not certain. However there are perhaps better methods which you can use, which are called at various stages in the elements lifecycle.
That said, can I ask why you need to use this particular method to add the children. It is probably much easier to do it with the template repeat like so:
<!DOCTYPE html>
<html>
<body>
<element name="top-menu" constructor="TopMenu" extends="div">
<template>
<div>
Top Menu
<ul id="top-menu-list">
<li template repeat="item in menuItems">{{item}}</li>
</ul>
</div>
</template>
<script type="application/dart" src="topmenu-element.dart"></script>
</element>
</body>
</html>
Then there's no need to put any of your menu display code in your constructor.
The following
main.html
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<p id="test" draggable="true">hello world</p>
<script type="application/dart" src="main.dart"></script>
<!-- for this next line to work, your pubspec.yaml file must have a dependency on 'browser' -->
<script src="packages/browser/dart.js"></script>
</body>
</html>
and main.dart
import 'dart:html';
void main() {
var elem = query('#test');
elem.onDragStart.listen((evt) {
evt.clipboardData.setData('text/html', elem.innerHtml);
});
}
are producing the exception
The null object does not have a method 'setData'.
NoSuchMethodError : method not found: 'setData'
Receiver: null
Arguments: ["text/html", "hello world"]
I've searched, but can find no relevant information about what I could possibly be doing wrong, or about clipboardData in dart at all (even the API is silent on the issue, and the source dart:html file just points to "native code"
(From my comment to the original question)
Use this instead:
evt.dataTransfer.setData('text/html', elem.innerHtml);
It is an attribute on MouseEvent (api ref) rather than the base Event class, and you can get autocomplete and remove editor warnings by explicitly declaring that evt is of type MouseEvent:
elem.onDragStart.listen((MouseEvent evt) {
evt.dataTransfer.setData('text/html', elem.innerHtml);
});
clipboardData seems to have been deprecated without warning. In web_ui components (where I first observed this), the dataTransfer attribute is not recognised by the editor as a valid attribute on instances of Event. I can't find any reference on the web as to why this change was made (the API docs don't say anything on the matter and I couldn't find any recent posts on the discussion board)...