Assume we have container polymer element and another dummy polymer element. Container polymer element has div block for inserting another polymers.
container_polymer.html
<polymer-element name='container-polymer'>
<template>
<div id="container">
</div>
<button on-click="{{first}}">show first</button>
<button on-click="{{firstPrepared}}">show first prepared</button>
<button on-click="{{second}}">show second</button>
</template>
<script type="application/dart" src="container_polymer.dart">
</script>
</polymer-element>
There are three buttons for inserting dummy polymers:
prepareElement()
on this polymer. container_polymer.dart
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'dummy_polymer.dart';
@CustomTag('container-polymer')
class ContainerPolymer extends PolymerElement {
PolymerElement firstPolymer, secondPolymer, currentPolymer;
Element container;
ContainerPolymer.created() : super.created();
void enteredView() {
super.enteredView();
container = $['container'];
}
void first(Event e, var detail, Node target) {
showFirst(false);
}
void firstPrepared(Event e, var detail, Node target) {
showFirst(true);
}
void showFirst(bool prepare) {
if (firstPolymer == null) {
DummyPolymer dummyPolymer = new Element.tag("dummy-polymer");
dummyPolymer.title = "first";
firstPolymer = dummyPolymer;
}
if (currentPolymer != firstPolymer) {
if (secondPolymer != null) {
secondPolymer.remove();
}
if (prepare) {
firstPolymer.prepareElement();
}
currentPolymer = firstPolymer;
container.children.add(firstPolymer);
}
}
void second(Event e, var detail, Node target){
if (currentPolymer != secondPolymer) {
DummyPolymer dummyPolymer = new Element.tag("dummy-polymer");
dummyPolymer.title = "second";
secondPolymer = dummyPolymer;
if (firstPolymer != null) {
firstPolymer.remove();
}
currentPolymer = secondPolymer;
container.children.add(secondPolymer);
}
}
}
Dummy polymer has several observable properties in order to test binding works. When you click inside this polymer it changes background color of root div, background color of title div and increases counter. Also it has input for detecting if state of polymer element was changed and block with white background for testing usage of parent style.
dummy_polymer.html
<polymer-element name='dummy-polymer'>
<template>
<div style="width: 500px; height: 300px; background-color: {{color}}" on-click="{{changeColor}}">
<div id="title">
<h1>{{title}}</h1>
<span>Clicks: {{clicks}}</span>
</div>
<input type="text" />
<div class="external">Parent style block: background should be white</div>
</div>
</template>
<script type="application/dart" src="dummy_polymer.dart">
</script>
</polymer-element>
dummy_polymer.dart
import 'package:polymer/polymer.dart';
import 'dart:html';
@CustomTag('dummy-polymer')
class DummyPolymer extends PolymerElement {
@observable String color = "red";
@observable String title;
@observable num clicks = 0;
Element titleElement;
DummyPolymer.created() : super.created() {
var root = getShadowRoot('dummy-polymer');
root.applyAuthorStyles = true;
}
void enteredView() {
super.enteredView();
titleElement = $['title'];
}
void changeColor(Event e, var detail, Node target){
clicks++;
if (color == "red") {
color = "green";
}
else if (color == "green") {
color = "blue";
}
else {
color = "red";
}
titleElement.style.backgroundColor = color;
}
}
Test page hosted here http://dart-style-binding-test.herokuapp.com/
So, to reproduce my issue do following:
Binding to observable properties doesn't work anymore. But on-click
handler works, you can see it when background color of top area changing. It's implemented by changing element's backgroundColor
property directly:
titleElement.style.backgroundColor = color;
So, my question is: how to update binding mechanism properly after existing polymer was inserted into DOM again?
There is one way to do it dirty using 'show first prepared' button. It calls prepareElement()
on first element before inserting into container. So, do following:
Note: after first element had been inserted with 'show first prepared' button, bindings works well even after first element was inserted with 'show first' button.
Code here https://github.com/petalvlad/dart-style-binding-test
I have not tried it myself but it seems reasonable. I hope the author doesn't mind coping his answer from Detached observables when re-using element.
Having looked into the polymer.js information bit I have found that there is a cancelUnbindAll function which must be called when the element is created or a preventDispose property set to true.
For anyone that might need to do the same, in the Dart implementation you must call cancelUnbindAll in the detached function after the super call, as follows:
void detached()
{
super.detached();
this.cancelUnbindAll(preventCascade: true);
}
Alternatively, you can simply override the preventDispose property in your custom element:
bool get preventDispose => true;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With