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) {}
}
Related
Say I have a polymer-element <polymer-element> <div id="foo"> {{html}} </div> </polymer-element>, where html is supposed to be a HTML formated string, like <p>blah</p>, what I want is, when html changes, the polymer-element also changes, and use html as its innerHtml, i.e. auto convert the string to an element and insert it as foo's child.
Can polymer/polymer_expression do this for me, or I have to do a querySelector(), then set html as innerHtml manually?
My solution is a custom element that extends a div and uses the DocumentFragment class to parse HTML strings into the DOM via data binding.
From my Github gist
<!-- Polymer Dart element that allows HTML to be inserted into the DOM via data binding -->
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="html-display" extends="div">
<script type="application/dart">
import 'dart:html';
import 'package:polymer/polymer.dart';
#CustomTag('html-display')
class HtmlDisplay extends DivElement with Polymer, Observable {
#published String htmlContent;
// we need this stuff because we're extending <div> instead of PolymerElement
factory HtmlDisplay() => new Element.tag('div', 'html-display');
HtmlDisplay.created() : super.created() {
polymerCreated();
}
#override void attached() {
super.attached();
}
// respond to any change in the "htmlContent" attribute
void htmlContentChanged(oldValue) {
if (htmlContent == null) {
htmlContent = "";
}
// creating a DocumentFragment allows for HTML parsing
this.nodes..clear()..add(new DocumentFragment.html("$htmlContent"));
}
}
</script>
</polymer-element>
<!--
Once you've imported the Polymer element's HTML file, you can use it from another Polymer element like so:
<link rel="import" href="html_display.html">
<div is="html-display" htmlContent="{{htmlString}}"></div>
*htmlString* can be something like "I <em>love</em> Polymer Dart!"
-->
I use solution as described in https://stackoverflow.com/a/20869025/789338.
The key class is DocumentFragment.
The official way to do it is described in the doc: https://www.polymer-project.org/docs/polymer/databinding-advanced.html#boundhtml
The example on the doc:
<polymer-element name="my-element">
<template>
<div id="message_area"></div>
</template>
<script>
Polymer({
message: 'hi there',
ready: function() {
this.injectBoundHTML('<b>{{message}}</b>', this.$.message_area);
}
});
</script>
</polymer-element>
I saw several posts here but I still can't succeed display anything...
I try to run the example in the source code.
https://github.com/dart-lang/core-elements/blob/master/lib/core_list_dart.html
this is my dart code
#CustomTag('exercise-list')
class ExerciseList extends PolymerElement {
#observable int testBind = 50000;
#observable ObservableList data;
#observable int index;
#observable bool selected;
ExerciseList.created() : super.created();
#override
void onReady() {
data = toObservable([
new Person('Bob', true),
new Person('Tim', false)
]);
}
}
class Person extends Observable {
#observable String name;
#observable bool checked;
Person(this.name, this.checked);
}
<link rel="import" href="../../../packages/polymer/polymer.html">
<link rel="import" href="../../../packages/core_elements/core_icons.html">
<link rel="import" href="../../../packages/core_elements/core_list_dart.html">
<polymer-element name="exercise-list">
<template>
test : {{testBind}}
<core-icon icon="star"></core-icon>
<core-list-dart data="{{data}}">
<template>
<div class="row {{ {selected: selected} }}" style="height: 80px">
List row: {{index}}, User data from model: {{model.name}}
<input type="checkbox" checked="{{model.checked}}">
</div>
</template>
</core-list-dart>
</template>
<script type="application/dart" src="exercise_list.dart"></script>
</polymer-element>
name: app
version: 0.0.1
description: app
environment:
sdk: '>=1.2.0 <2.0.0'
dependencies:
browser: any
guinness: any
paper_elements: '>=0.6.0+2 <0.7.0'
core_elements: '>=0.5.0+2 <0.6.0'
polymer: '>=0.15.3 <0.16.0'
unittest: any
transformers:
- polymer:
entry_points: web/index.html
The value testBing and the core-icon are well displayed. It's weird I can't understand where is my problem... Hope you will find the problem. Cheers !
Update
Here is an example of the bare minimum code to display something with core-list-dart. note the mandatory fields in the model !!!
Update
There are a few issues with your code:
exercise_list.dart
You are overriding onReady which is a getter not a method and can't
be overridden. You want to override ready instead.
When I load the page I get exceptions telling me that Person doesn't
have a selected or index property. I added them to the class to
get rid of the error without investigating why this is necessary.
class Person extends Observable {
#observable String name;
#observable bool checked;
bool selected = false; // <== added
int index; // <== added
Person(this.name, this.checked);
}
exercise_list.html
I removed model. from {{model.name}} and {{model.checked}}
Now the list is displayed.
All these things were reported by the development environment. I use WebStorm but I'm sure the same hints and errors would be shown by DartEditor and also by Dartium when run directly (shown in the developer tools console).
You can't reference fields of your exercise_list element in the template element passed to core-list-dart because the template is removed and applied inside the core-list-dart which changes its scope.
This is why selected and index didn't work here.
Old
I guess the problem is that the core-list-dart needs an explicit height to be displayed but your code doesn't show how it is added to your page. (see also this discussion https://github.com/Polymer/core-list/issues/47#issuecomment-63126241)
The height is probably only applied if you set your element to display: block
<polymer-element name="exercise-list">
<template>
<style>
:host {
display: block;
}
core-list-dart {
height: 500px;
}
</style>
....
The Dart code for my Polymer element looks like this:
#CustomTag('my-element')
class MyElement extends PolymerElement {
final List<String> colors = toObservable(['red', 'green', 'blue']);
MyElement.created() : super.created();
}
And the HTML looks like this:
<polymer-element name="my-element">
<template>
<style>
.core-selected {
font-weight: bold;
}
</style>
<core-selector id="selector" selected="1">
<template repeat="{{color in colors}}">
<div value="{{color}}">{{color}}</div>
</template>
</core-selector>
<hr>
<!-- Prints the selected index, but does not update -->
<div>{{$['selector'].selected]}}</div>
</template>
<script type="application/dart" src="my_element.dart"></script>
</polymer-element>
Using <div>{{$['selector'].selected]}}</div> correctly shows the index of the selected color, but picking a different color does not refresh the value of selected. Am I using this correctly? Or is this a bug?
I agree it's a bug, but in the meantime you can work around it like this
<core-selector id="selector" selected="{{selected}}">
...
<div>{{selected}}</div>
with the backing code containing the obvious
#observable int selected = 1;
I do wonder if your version works when used in a pure JS environment? But that's another question.
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');
Trying to use Select component in custom element as follows. button click works but when an item is selected in the list, the 'selected' and 'value' attribute does not change and list always shows the first element selected. Binding seems to work from dart to html but not from html to dart. Help please!
<html>
<head>
<title>index</title>
<script src="packages/polymer/boot.js"></script>
</head>
<body>
<polymer-element name="my-element" extends="div">
<template >
<button on-click='bclick'>Add new fruit</button>
<select selectedIndex="{{selected}}" value="{{value}}">
<option template repeat="{{fruit in fruits}}">{{fruit}}</option>
</select>
<div>
You selected option {{selected}} with value-from-list
{{fruits[selected]}} and value-from-binding {{value}}
</div>
</template>
<script type="application/dart" src="polyselect.dart"></script>
</polymer-element>
<my-element></my-element>
<script type="application/dart">main() {}</script>
</body>
</html>
Dart file is as follows:
import 'package:polymer/polymer.dart';
import 'dart:html';
#CustomTag('my-element')
class MyElement extends PolymerElement {
#observable int selected = 1; // Make sure this is not null.
// Set it to the default selection index.
List fruits = toObservable(['apples', 'bananas', 'pears', 'cherry', 'grapes']);
#observable String value = '';
void bclick(Event e) {
fruits.add("passion fruit");
}
}
I had to mixin the ObservableMixin class.
class MyElement extends PolymerElement with ObservableMixin