core-style and classes does not seem to work - dart

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/

Related

How to scroll to the last element of iron-list (dart polymer 1.0)?

I want to scroll to the last element of iron-list after each update of its model but calling IronList.scrollToIndex() shows only part of the list. More clearly, I have polymer element:
#PolymerRegister('main-app')
class MainApp extends PolymerElement {
#property
List<String> items = [];
MainApp.created() : super.created();
#reflectable
void onAdd([_, __]){
var fst = items.length;
var lst = new List.generate(30, (x) => (fst+x).toString());
addAll("items", lst);
($['list'] as IronList).scrollToIndex(items.length-1);
}
}
html:
<dom-module id="main-app">
<template>
<style>
#list {
height: 100px;
width: 100px;
}
</style>
<iron-list items="{{items}}" id="list">
<template>
<div>{{item}}</div>
</template>
</iron-list>
<paper-button raised on-tap="onAdd">add</paper-button>
</template>
</dom-module>
When I click on the button for the first time it gives me:
What's wrong here? How to update the view properly?
(package versions: polymer 1.0.0-rc.6, polymer_elements 1.0.0-rc.3, polymer_interop 1.0.0-rc.5)

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

Polymer core-selector does not refresh

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.

In Polymer.js children of a template have a reference to the template, how can this be done in Polymer.dart

When I have a reference to an element that was produced by a <template>, in Polymer.js such elements have an attribute templateInstance that provides a references to its template like it's used here:
https://github.com/PolymerLabs/polymer-selector/blob/master/polymer-selector.html#L286
Polymer >= 1.0.0
#reflectable
void someClickHandler(dom.Event event, [_]) {
// for native events (like on-click)
var model = new DomRepeatModel.fromEvent(event);
// or for custom events (like on-tap, works also for native events)
var model = new DomRepeatModel.fromEvent(convertToJs(event));
var value = model.jsElement['items'];
// or
var value = model.jsElement[$['mylist'].attributes['as']];
// if you used the `as="somename"`
// in your <core-list> or <template is="dom-repeat">
}
There is an open issue related to custom events: https://github.com/dart-lang/polymer-dart/issues/624
Polymer <= 0.16.0
EDIT
The example below needs only this 3 lines, the other code is just for demonstration purposes
import 'package:template_binding/template_binding.dart' as tb;
tb.TemplateInstance ti = tb.nodeBind(e.target).templateInstance;
var value = ti.model.value as Inner;
EDIT END
This functionality was added recently (see https://code.google.com/p/dart/issues/detail?id=17462)
I created an example to test how it works:
index.html
<!DOCTYPE html>
<html>
<head>
<title>nested-repeat</title>
<!-- <script src="packages/web_components/platform.js"></script>
not necessary anymore with Polymer >= 0.14.0 -->
<script src="packages/web_components/dart_support.js"></script>
<link rel="import" href="nested_templates.html">
</head>
<body>
<nested-templates></nested-templates>
<script type="application/dart">export 'package:polymer/init.dart';</script>
</body>
</html>
nested_templates.html
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="nested-templates">
<template>
<style>
:host { display: block; height: 100%; }
ul { margin: 0; padding: 0; }
li { font-size: 0.85rem; padding-left: 0.75rem; }
li:hover { background: lightgrey; cursor: pointer; }
li.selected { color: red; }
</style>
<div>
<template repeat="{{o in outer}}">
<strong>{{o.name}}</strong>
<ul>
<template repeat="{{i in o.inner}}">
<li id="{{i.name}}" on-click="{{innerClickHandler}}" template-value='{{i}}'>{{i.name}}</li>
</template>
</ul>
</template>
</div>
</template>
<script type="application/dart" src="nested_templates.dart"></script>
</polymer-element>
nested_templates.dart
import 'dart:html' as dom;
import 'package:polymer/polymer.dart';
import 'package:template_binding/template_binding.dart' as tb;
#CustomTag('nested-templates')
class NestedTemplates extends PolymerElement {
NestedTemplates.created() : super.created();
#observable List<Outer> outer = toObservable([new Outer('o1', toObservable(
[new Inner('a'), new Inner('b')])), new Outer('o2', toObservable([new Inner(
'c'), new Inner('d')]))], deep: true);
void innerClickHandler(dom.Event e) {
shadowRoot.querySelectorAll('li.selected').forEach((e) => (e as
dom.HtmlElement).classes.remove('selected'));
(e.target as dom.HtmlElement).classes.add('selected');
tb.TemplateInstance ti = tb.nodeBind(e.target).templateInstance; // get access to the TemplateInstance of the element
// TemplateInstance provides access to the model and the actual value
var value = ti.model.value as Inner;
print('name: ${value.name}'); // works
print('equals: ${value == (e.target as dom.HtmlElement).attributes['template-value']}'); // prints "false"
print(
'${(e.target as dom.HtmlElement).attributes['template-value']}'); // prints "Instance of 'Inner'"
// shows that the attribute only has the result of 'toString()' but not the actual value of type 'Inner'
print(
'${(e.target as dom.HtmlElement).attributes['template-value'].runtimeType}'); // prints "String"
}
}
class Inner extends Observable {
#observable String name;
Inner(this.name);
}
class Outer extends Observable {
#observable String name;
List<Inner> inner;
Outer(this.name, this.inner);
}

How to bind repeating nested templates to complex models

Eventually I want to bind templates to a tree model, but to understand how binding works beyond object properties (simple or chained), lists, and maps, I've created a two-level set of repeating templates bound to a corresponding Dart model. Each item in the outer list contains an inner list.
o1
a
b
o2
c
d
When I select an inner item (for example 'd'), the click handler highlights the item and appends an Inner object 'e' to the 'o2' Outer object's list. Inspecting the model in the debugger shows that 'e' has been added to the model, but it is not being added as an 'li' element to the HTML list. How do I revise my code so that the inner template detects the change?
HTML
<polymer-element name="nested-templates">
<template>
<style>
:host { display: block; height: 100%; }
ul { margin: 0; padding: 0; }
li { font-size: 0.85rem; padding-left: 0.75rem; }
li:hover { background: lightgrey; cursor: pointer; }
li.selected { color: red; }
</style>
<div>
<template repeat="{{o in outer}}">
<strong>{{o.name}}</strong>
<ul>
<template repeat="{{i in o.inner}}">
<li id="{{i.name}}" on-click="{{innerClickHandler}}">{{i.name}}</li>
</template>
</ul>
</template>
</div>
</template>
<script type="application/dart" src="nested_templates.dart"></script>
Dart
import 'dart:html';
import 'package:polymer/polymer.dart';
#CustomTag('nested-templates')
class NestedTemplates extends PolymerElement {
#observable List<Outer> outer = toObservable([
new Outer('o1', [ new Inner('a'), new Inner('b')]),
new Outer('o2', [ new Inner('c'), new Inner('d')])
], deep: true);
void innerClickHandler(Event e, Map detail, HtmlElement target) {
target.classes.add('selected');
outer[1].inner.add(new Inner('e'));
}
NestedTemplates.created() : super.created();
}
class Inner extends Observable {
String name;
Inner(this.name);
}
class Outer extends Observable {
String name;
List<Inner> inner;
Outer(this.name, this.inner);
}
pubspec.yaml
dependencies:
...
polymer: 0.10.1+1
polymer_expressions: 0.11.0
...
dependency_overrides:
polymer_expressions: '0.11.0'
You need toObservable() for your inner too
new Outer('o1', toObservable([ new Inner('a'), new Inner('b')])),

Resources