Refer to sibling Polymer element in Dart? - dart

For the past few hours I have been struggling to refer to a sibling element within my Polymer project. Imagine the following setup:
/* main.html */
<link rel="import" href="siblingA.html">
<link rel="import" href="siblingB.html">
<polymer-element name="app-main">
<template>
<app-siblingA></app-siblingA>
<app-siblingB></app-siblingB>
</template>
<script type="application/dart" src="main.dart"></script>
</polymer-element>
/* siblingA.html, nothing special about it */
<polymer-element name="app-siblingA">
<template>
<button on-click="{{doSomething))">Do something</button>
</template>
<script type="application/dart" src="siblingA.dart"></script>
</polymer-element>
/* siblingA.dart */
import 'package:polymer/polymer.dart';
import 'dart:html';
#CustomTag('app-siblingA')
class SiblingA extends PolymerElement {
bool get applyAuthorStyles => true;
SiblingA.created() : super.created() {
}
void doSomething(MouseEvent e, var detail, Node target) {
var profile = document.querySelector('app-siblingB');
print(profile); // This is always null, why?
}
}
Now I can get my app-main node from the document, but it fails on getting sibling elements. I have tried getting the sibling element via the shadowRoot without success.
How can I get a sibling element, in this case app-siblingB, from the document or shadowRoot?

Your siblings are within the shadowDOM of <app-main>. document.querySelector() doesn't reach into the shadowDOM of an element.
This should work
(parentNode as ShadowRoot).querySelector('app-siblingB');

Related

Send event from parent to child element in polymer.dart

I am trying to fire an event from a polymer element, and listen for that event in an element that is inside of it.
These are the four files of consequence:
main_app.html
<link rel="import" href="../../packages/paper_elements/paper_input.html">
<link rel="import" href="../../packages/paper_elements/paper_button.html">
<link rel="import" href="canvas_container.html">;
<polymer-element name="main-app">
<template>
<paper-button on-click="{{onButtonClicked}}">text</paper-button>
<canvas-container"></canvas-container>
</template>
<script type="application/dart" src="main_app.dart"></script>
</polymer-element>
main_app.dart
import 'dart:html';
import 'package:polymer/polymer.dart';
#CustomTag('main-app')
class MainApp extends PolymerElement {
MainApp.created() : super.created();
onButtonClicked(Event event, var detail, Node sender) {
print('button clicked');
fire('test');
}
ready() {
super.ready();
}
}
canvas_container.html
<polymer-element name="canvas-container">
<div on-test="{{testAction}}">
<template>
<div>
<canvas id="canvas"></canvas>
</div>
</template>
</div>
<script type="application/dart" src="canvas_container.dart"></script>
</polymer-element>
canvas_container.dart
import 'dart:html';
import 'package:Compbook/stave.dart';
import 'package:Compbook/clef.dart';
import 'package:polymer/polymer.dart';
#CustomTag('canvas-container')
class CanvasContainer extends PolymerElement {
CanvasElement canvas;
CanvasRenderingContext2D context;
CanvasContainer.created() : super.created();
ready() {
this.canvas = $['canvas'];
canvas.width = 1000;
canvas.height = 1000;
context = canvas.context2D;
testAction(Event e, var detail, Node sender) {
print('event has been received');
}
}
When I click the paper-button, the event trigger correctly, but it is not being received by the canvas-container at all. Any insight into the problem is appreciated
The Polymer documentation has a section about this topic https://www.polymer-project.org/0.5/articles/communication.html#sending-messages-to-siblingschildren
Subscribe to the event on the parent and re-fire it on each child.

Polymer Dart core-style ref not resolved

When I pass parameters to a Polymer element the core-style ref does not get resolved.
Here is the child code:
<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="packages/core_elements/core_style.html">
<core-style id="s1" unresolved> div { background: yellow; } </core-style>
<core-style id="s2" unresolved> div { background: pink; } </core-style>
<polymer-element name='test-cell' attributes='s t' noscript>
<template>
<core-style ref="{{s}}"></core-style>
<div>{{t}}</div>
</template>
</polymer-element>
As you can see, there are two core styles.
Here is the parent code. It takes a List and instantiates 'test-cell' with text and a style reference.
<polymer-element name='test-rows'>
<template>
<template repeat='{{ v in x }}'>
<test-cell s={{v.s}} t={{v.t}}></test-cell>
</template>
</template>
</polymer-element>
In this simple example the Dart code is inline. Here it is:
<script type='application/dart'>
import 'package:polymer/polymer.dart';
//======================================
class Info {
String s, t;
Info(this.s, this.t) {}
}
//======================================
#CustomTag('test-rows')
class TestRows extends PolymerElement {
#observable List<Info> x = toObservable([]);
//-----------------------------------
TestRows.created() : super.created() {
x.add(toObservable(new Info('s1', 'first' )));
x.add(toObservable(new Info('s2', 'second')));
}
}
</script>
In the generated HTML the text comes through OK but the core-style instances both have
ref="{{s}}"
and the styles are not applied. Can I force resolution of the style ref parameter by some alternative annotation? It is essentially a final/const.
Update
I think the problem is your noscript in your test-cell element.
Binding doesn't work in Dart with Polymer elements without a backing script (noscript) as far as I know.
I think in your case the <test-cell> element needs a field
#observable
var s;
to make this work.
Original
Your code doesn't show if you ever assign a value to s.
I doubt toObservable works on plain Dart objects. This is for lists and maps as far as I know.
The Info class should look like this and you don't need to use toObservable() with it.
class Info extends Object with Observable {
#observable
String s;
#observable
String t;
Info(this.s, this.t) {}
}

Prevent paper-dialog from automatically closing

Hello:
I have a paper-dialog element in a page:
<paper-dialog ... id="autom_desc_dialog" autoCloseDisabled>
...
<paper-button ... id="automatizar" affirmative autofocus disabled></paper-button>
</paper-dialog>
and I have an event listener that handles the paper-button click:
var auto_btn = querySelector('#automatizar');
auto_btn.on["click"].listen((Event e) {
// Some AJAX stuff
});
What I want is that in some cases, to be able to prevent the dialog from closing, I've tried event.preventDefault(), event.stopImmediatePropagation(), event.stopPropagation() but no success.
Thanks in advance.
You don't need to remove affirmative/dismissive attributes as they are used for layout. Polymer dialog docs are wrong (I've opened a GH issue) the default value for closeSelector is '[dismissive],[affirmative]' and not "", you just need to set closeSelector to "" and it won't close the dialog on clicking the buttons.
You just need to remove the affirmative attribute from the button then you have full control of the behavior.
app-element.dart
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'package:paper_elements/paper_dialog.dart';
/**
* A Polymer app-element element.
*/
#CustomTag('app-element')
class AppElement extends PolymerElement {
/// Constructor used to create instance of AppElement.
AppElement.created() : super.created() {
}
void openClickHandler(Event e) {
print(e);
($['autom_desc_dialog'] as PaperDialog).opened = true;
}
void closeClickHandler(Event e){
if(true /* some condition */) {
($['autom_desc_dialog'] as PaperDialog).opened = false;
}
}
}
app_element.html
<!-- import polymer-element's definition -->
<link rel="import" href="../../packages/polymer/polymer.html">
<link rel="import" href="../../packages/paper_elements/paper_dialog.html">
<link rel="import" href="../../packages/paper_elements/paper_button.html">
<polymer-element name="app-element">
<template>
<style>
:host {
display: block;
}
</style>
<paper-dialog id="autom_desc_dialog" autoCloseDisabled>
<div>paper dialog</div>
<paper-button id="automatizar" autofocus label="close" on-click="{{closeClickHandler}}"></paper-button>
</paper-dialog>
<paper-button id="open" autofocus label="open" on-click="{{openClickHandler}}"></paper-button>
</template>
<script type="application/dart" src="app_element.dart"></script>
</polymer-element>

How to access light DOM in Polymer.dart?

I'm looking for a way to access light DOM inside a custom Polymer.dart element.
my_element.html
<link rel="import" href="../../../../packages/polymer/polymer.html">
<polymer-element name="my-element">
<template>
<content></content>
</template>
<script type="application/dart" src="my_element.dart"></script>
</polymer-element>
my_element.dart
import 'package:polymer/polymer.dart';
import 'dart:html';
#CustomTag('my-element')
class MyElement extends PolymerElement {
MyElement.created() : super.created() {}
void attached() {
// How to access the light DOM of this element?
}
}
To access light DOM simply call this.querySelector('<your-selector>')
To access the shadow DOM call shadowRoot.querySelector('<your-selector>')

When dynamically adding dart polymer elements, how do I get observable variables to on DOM

I am trying to change the default web application that uses the polymer library so that the polymer element is created and added to the DOM from DART code rather than including in the HTML. I have succeeded in adding the element to the DOM, but my observable variable are not being updated on the DOM. The events are being fired, and the values are changing. I have got the DOM to update using Observable.dirtyCheck(), however, this is apparently expensive, so am trying to figure out how to get polymer to update dom without dirtyCheck().
So, In short, how to I get rid of Observable.dirtyCheck()???
dynamiccreate.dart
library dynamiccreate;
import 'dart:html';
import 'package:polymer/polymer.dart';
main() {
initPolymer();
//create click-counter element at runtime from DART, not HTML
var NewElement = new Element.tag('click-counter');
NewElement.setAttribute("count", "5");
//Add to DOM
querySelector('#sample_container_id').children.add(NewElement);
}
dynamiccreate.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample app</title>
<link rel="stylesheet" href="dynamiccreate.css">
<!-- import the click-counter -->
<link rel="import" href="clickcounter.html">
<!-- <script type="application/dart">export 'package:polymer/init.dart';</script> -->
<script src="packages/browser/dart.js"></script>
</head>
<body>
<h1>DynamicCreate</h1>
<p>Hello world from Dart!</p>
<div id="sample_container_id">
<!-- <click-counter count="5"></click-counter> -->
</div>
<script src="dynamiccreate.dart" type="application/dart"></script>
</body>
</html>
clickcounter.dart
import 'package:polymer/polymer.dart';
/**
* A Polymer click counter element.
*/
#CustomTag('click-counter')
class ClickCounter extends PolymerElement {
#published int count = 0;
ClickCounter.created() : super.created() {
}
//increment gets called when dynamically adding object at runtime
//But does not update count on DOM
void increment() {
count++;
//Have to add this to update count in DOM
Observable.dirtyCheck(); //<<<---How do I get rid of this???
}
}
clickcounter.html
<polymer-element name="click-counter" attributes="count">
<template>
<style>
div {
font-size: 24pt;
text-align: center;
margin-top: 140px;
}
button {
font-size: 24pt;
margin-bottom: 20px;
}
</style>
<div>
<button on-click="{{increment}}">Click me</button><br>
<span>(click count: {{count}})</span>
</div>
</template>
<script type="application/dart" src="clickcounter.dart"></script>
</polymer-element>
Change your dynamiccreate.dart file to look like this, and the counter starts incrementing in the UI:
library dynamiccreate;
import 'dart:html';
import 'package:polymer/polymer.dart';
main() {
initPolymer().run(() {
var newElement = new Element.tag('click-counter');
newElement.setAttribute("count", "15");
querySelector('#sample_container_id').children.add(newElement);
});
}
Nit: name your variable newElement, not NewElement. Fixed here.

Resources