Polymer core-selector does not refresh - dart

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.

Related

core-style and classes does not seem to work

I am trying to understand core-style. I noticed that in all examples I have seen so far, only elements eg Button are referenced in a core-style - there is no class reference (eg .blue). I tried to place a class reference in the core-style but it does not render. Please see the example below
.html
<link href='../../../../packages/polymer/polymer.html' rel='import' >
<link href='../../../../packages/core_elements/core_style.html' rel='import' >
<polymer-element name='blue-theme'>
<template>
<core-style id='blue-theme'>
:host {
background-color: red;
.lb-container1 {
background-color: {{lb50}};
padding-top: 5px;
padding-bottom: 5px;
width: {{width}}
}
}
</core-style>
</template>
<script type='application/dart' src='blue_theme.dart'></script>
</polymer-element>
.dart
import 'package:polymer/polymer.dart';
import 'package:epimss_shared/epimss_shared_client.dart' hide DataEvent;
#CustomTag( 'blue-theme' )
class BlueTheme extends PolymerElement
{
String topic = '';
#observable String lb50 = LightBlue['50'];
#observable String lb100 = LightBlue['100'];
#observable String lb200 = LightBlue['200'];
BlueTheme.created() : super.created();
#published
String get width => readValue( #width );
set width(String value) => writeValue( #width, value );
#override
void attached()
{
super.attached();
topic = this.dataset['topic'];
}
}
The above code does not render.
Thanks
You only created a <core-style> producer (provides reusable styles). What you also need is a <core-style> consumer.
<core-style ref="blue-theme"></core-style>
I haven't used it myself but I think just adding this line should solve the problem. You can have the producer and consumer in different elements. That is rather the point of the element. Define a style once and reuse it just by referencing.
This tutorial looks good so far https://pascalprecht.github.io/2014/08/01/sharing-styles-across-web-components-with-polymer-and-core-style/

how to display simple information using <core-list-dart>

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>
....

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) {}
}

TextArea Resizing in Dart during DOM Initialization

I'm trying to make a text area that resizes dynamically in Dart based on the height of its contents.
I have a textarea element defined in a polymer element in Dart like so:
<polymer-element name="page-content">
<template>
{{title}}
<ul>
<template repeat="{{element in elist | enumerate}}">
<li value={{element.index}}><textarea class="{{element.value.type}}" resize="none" on-keypress="{{resize}}" on-change="{{updateDatabase}}">{{element.value.content}}</textarea><div on-click="{{deleteElement}}">X</div></li>
</template>
</ul>
</template>
</polymer-element>
When any text is entered into the textarea, the resize method is called and properly resizes the text-area to adjust its height appropriately.
I am not sure how to call the resize method right when the element is loaded into the DOM. I have tried adding on-load="{{resize}}" to the textarea or even querying all the textareas and adjusting their sizes. Nothing seems to be working. My intutition tells me there should be an easy way to do this.
If it helps, my resize method in dart looks like this:
void resize(Event event, var detail, var target) {
Element element = event.target;
print(element.scrollHeight);
element.style.height = "1px";
element.style.height = "${element.scrollHeight}px";
}
This is an interesting question.
I think the best approach would be to wrap the textarea in some autosize-textarea and there add
<polymer-element name="autosize-textarea">
<template>
<textarea id="inner" class="{{element.value.type}}" resize="none"
on-keypress="{{resize}}">
{{element.value.content}}</textarea>
</template>
</polymer-element>
import 'dart:html';
import 'package:polymer/polymer.dart';
#CustomTag('autosize-textarea')
class AutosizeTextarea extends PolymerElement {
AutosizeTextarea.created() : super.created();
#published
Element element;
void attached() {
super.attached();
resize(null, null, null);
}
void resize(Event event, var detail, var target) {
Element textarea $['inner'];
print(textarea.scrollHeight);
textarea.style.height = "1px";
textarea.style.height = "${textarea.scrollHeight}px";
}
}
and the use it like
<link rel="import" href="autosize_textarea.html">
<polymer-element name="page-content">
<template>
{{title}}
<ul>
<template repeat="{{element in elist | enumerate}}">
<li value={{element.index}}>
<autosize-textarea on-change="{{updateDatabase}}" element="{{element}}></autosize-textarea>
<div on-click="{{deleteElement}}">X</div>
</li>
</template>
</ul>
</template>
</polymer-element>
I'm not sure if I understand your code correctly because you named the item created from template repeat element and also the element you got from event.target. I'm not sure if/how they are related.
Not tested but I think it should work.
The code that I worked out is very similar to what Günter Zöchbauer suggested. It queries the shadow DOM (something I did not think to do) to get all the text areas at once (instead of just one) and update their heights accordingly.
The method could be in attached() or after any place where the content is dynamically fetched from the database in my case.
void updatePageSizes() {
var items = shadowRoot.querySelectorAll("textarea");
var j = items.iterator;
while (j.moveNext()) {
j.current.style.height = "${element.scrollHeight}px";
j.current.style.backgroundColor = "blue";
}
}
Also, I figured out that, to my knowledge, it is not possible to call a function in Dart from each element added in an enumerated list in a polymer element. I guess this is just a limitation of Dart.

Using Select Element in polymer dart component

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

Resources