I'm trying to build a reusable polymer web component that supports reordering items via drag and drop in a core-list. The interface I want is essentially the same as core-list
<reorderable-list id="list" data="{{data}}" height="60">
<template>
<some-reorderable-element>
</some-reorderable-element>
</template>
</reorderable-list>
My current thinking is that I want each row to be wrapped as follows
<a-container>
<draggable-member>
<some-reorderable-element>
</some-reorderable-element>
</draggable-member>
</a-container>
where a-container
always remains in place and is sized exactly the size of a row and draggable-member
gets detached on drag from a-container
and attached to the core-drag-drop
avatar. As a-container
remains in place this should keep the row there with just the background colour I'm hoping.
The part I'm struggling with is how to instantiate the above structure for each row.
I was heading down a path like
<core-list-dart id="list" data="{{data}}" height="{{height}}">
<template>
<a-container>
<draggable-member id="member" draggable="true">
<content></content>
</draggable-member>
</a-container>
</template>
</core-list-dart>
Not sure if this is heading in the right direction. Catch is that core-list
is only going to instantiate copies of a-container
. Somehow I'd need to instantiate copies of draggable-member
and the user provided content for each row too but not sure how best to do that or if this is even a good approach.
Edit
Well after pulling my hair out for a few hours I thought I had the answer by doing it programatically like
@CustomTag('reorderable-list')
class ReorderableList extends PolymerElement with Observable {
@published ObservableList data;
@published double height;
ReorderableList.created() : super.created() {
}
attached() {
final CoreList coreList = new Element.tag('core-list-dart');
coreList.data = data;
coreList.height = height;
final TemplateElement template = new Element.tag('template');
final MemberContainer mc = new Element.tag('member-container');
final ReorderableMember rm = new Element.tag('reorderable-member');
rm.children.addAll(children);
mc.append(rm);
template.content.append(mc);
coreList.append(template);
shadowRoot.append(coreList);
}
}
This almost gives me what I want but not quite as I'm not putting things in the shadow dom. Back to the drawing board :-(
Edit2
I thought I had it nailed but now it seems that the ContentElement behaves in mysterious ways.
When the row items are using <content></content>
then this content disappears when you detach the component from it's usual parent and add it to the avatar. Presumably the ContentElement works dynamically and can no longer find the associated content. I'll have to get a better understanding of how that works to see if I can get around it.
<link rel="import" href="../../../../packages/core_elements/core_style.html">
<link rel="import" href="../../../../packages/core_elements/core_drag_drop.html">
<core-style id="draggable-list-item" unresolved>
#row-container, #drag-container {
padding: none;
margin: none;
display: block;
}
#row-container {
border: solid 1px black;
}
}
</core-style>
<polymer-element name="draggable-list-item" on-drag-start="{{startDrag}}">
<template>
<core-style ref="draggable-list-item"></core-style>
<core-drag-drop></core-drag-drop>
<div id="row-container">
<drag-container id="drag-container">
<content></content>
</drag-container>
</div>
</template>
<script type="application/dart" src="draggable_list_item.dart"></script>
</polymer-element>
<polymer-element name="drag-container" draggable="true">
<template>
<style>
#foo {
border: solid 1px blue;
height: 100%;
width: 100%;
}
</style>
<div id="foo">
<p>Hola</p>
<content></content>
</div>
</template>
</polymer-element>
--
library ui.polymer.core.list.item.draggable;
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'package:logging/logging.dart';
import 'dart:js';
Logger _log = new Logger('ui.polymer.core.item.draggable');
@CustomTag('draggable-list-item')
class DraggableListItem extends PolymerElement with Observable {
bool multi;
DraggableListItem.created() : super.created() {
_log.finer('DraggableListItem.created');
}
void startDrag(CustomEvent e, JsObject dragInfo) {
_log.finest('DraggableListItem dragging ${identityHashCode(e)} '
'${e.target}, ${e.currentTarget}, ${e.detail}, ${dragInfo}');
_log.finest('e.target == e.currentTarget => ${identical(e.target, e.currentTarget)}');
final HtmlElement avatar = dragInfo['avatar'];
final rect = getBoundingClientRect();
avatar.style.setProperty('width', '${rect.width}px');
avatar.style.setProperty('height', '${rect.height}px');
final dragContainer = $['drag-container'];
final rowContainer = $['row-container'];
rowContainer.style.setProperty('width', '${rect.width}px');
rowContainer.style.setProperty('height', '${rect.height}px');
dragContainer.style.setProperty('width', '${rect.width}px');
dragContainer.style.setProperty('height', '${rect.height}px');
avatar.append(dragContainer.clone(true));
dragContainer.style.display = 'none';
dragInfo['drag'] = drag;
dragInfo['drop'] = drop;
}
drag(JsObject dragInfo) {
print('drag');
final HtmlElement avatar = dragInfo['avatar'];
print(avatar);
}
drop(JsObject dragInfo) {
print('drop');
final HtmlElement avatar = dragInfo['avatar'];
print(avatar);
}
}
@CustomTag('drag-container')
class DragContainer extends PolymerElement with Observable {
bool multi;
DragContainer.created() : super.created() {
_log.finer('DragContainer.created');
print('DragContainer.created');
}
}
--
<core-list-dart height="100" data="{{data}}">
<template>
<draggable-list-item>
<test-row></test-row>
</draggable-list-item>
</template>
</core-list-dart>