使用core-list和core-drag-drop构建可重新排序的列表(通过dnd)

时间:2014-10-06 22:16:28

标签: dart polymer dart-polymer

我正在尝试构建一个可重复使用的聚合物Web组件,该组件支持通过拖放核心列表重新排序项目。我想要的接口与core-list

基本相同
<reorderable-list id="list" data="{{data}}" height="60">
  <template>
    <some-reorderable-element>
    </some-reorderable-element>
  </template>
</reorderable-list>

我目前的想法是,我希望每行包装如下

<a-container>
    <draggable-member>
       <some-reorderable-element>
       </some-reorderable-element>
    </draggable-member>
</a-container>

其中a-container始终保持不变,且大小与行的大小完全相同,draggable-membera-container拖动时附加到core-drag-drop头像。当a-container仍然存在时,这应该保持那里的行只有我希望的背景颜色。

我正在努力解决的问题是如何为每一行实例化上述结构。

我正走在像

这样的道路上
<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>

不确定这是否朝着正确的方向发展。 Catch是core-list仅用于实例化a-container的副本。不知何故,我需要实例化draggable-member的副本以及每行的用户提供的内容,但不确定如何最好地做到这一点,或者这是否是一个好方法。

修改

好好把我的头发拉了几个小时之后,我觉得我的答案就像编程一样

@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);
  }
}

这几乎给了我想要的东西,但并不是因为我没有把东西放在阴影中。回到绘图板: - (

EDIT2

我以为我把它固定了,但现在看来ContentElement以神秘的方式运行。 当行项目使用<content></content>时,当您从常规父级中分离组件并将其添加到头像时,此内容将消失。据推测,ContentElement动态工作,无法再找到关联的内容。我必须更好地了解它是如何工作的,看看我能不能解决它。

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

2 个答案:

答案 0 :(得分:1)

到目前为止,我试图将<core-list-dart>包裹起来(没有拖放)。

import 'package:polymer/polymer.dart';
import 'package:core_elements/core_list_dart.dart';

@CustomTag('reorderable-list')

class ReorderableList extends PolymerElement {

  /// Constructor used to create instance of ReorderableList.
  ReorderableList.created() : super.created();

  @PublishedProperty(reflect: true)
  List<String> data;

  attached() {
    super.attached();
    var template = querySelector('template');
    var coreList = (shadowRoot.querySelector('core-list-dart') as CoreList);
    coreList.append(template);
  }
}
<link rel="import" href="../../packages/polymer/polymer.html">
<link rel="import" href="../../packages/core_elements/core_list_dart.html">

<polymer-element name="reorderable-list">
  <template>
    <core-list-dart data="{{data}}"></core-list-dart>
    <content></content>
  </template>
  <script type="application/dart" src="reorderable_list.dart"></script>
</polymer-element>

用法(与<core-list-dart>基本相同)

<link rel="import" href="../../packages/polymer/polymer.html">
<link rel="import" href="../../packages/core_elements/core_list_dart.html">
<link rel="import" href="drag_container.html">
<link rel="import" href="draggable_member.html">
<link rel="import" href="test_element.html">
<link rel="import" href="reorderable_list.html">

<polymer-element name="app-element">
  <template>
    reorderable-list
    <reorderable-list data="{{strings}}">
      <template id="app-element-reorderable">
        <drag-container>
          <draggable-member id="member" draggable="true">
            <test-element>{{name}}</test-element>
          </draggable-member>
        </drag-container>
      </template>
    </reorderable-list>

  </template>
  <script type="application/dart" src="app_element.dart"></script>
</polymer-element>
import 'package:polymer/polymer.dart';

class Item {
  String name;
  Item(this.name);
  bool selected = false;

  String toString() => name;
}

@CustomTag('app-element')

class AppElement extends PolymerElement {

  @observable
  List strings = toObservable([new Item('Anton'), new Item('Berta'), new Item('Caesar'), new Item('Dora')]);

  AppElement.created() : super.created();
}

我认为当<reorderable-list>实现drag-n-drop事件处理程序时它应该可以工作。

答案 1 :(得分:0)

我已将所有这些代码添加到https://bitbucket.org/andersmholmgren/ah_polymer_stuff。每个人都可以自由地利用这一点。

我现在非常接近。它的工作原理是我可以移动行。

最后一个障碍是我在拖动过程中丢失了头像中的部分行内容。我很确定它来自我的最后一招。

该元素现在定义为

<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">
      <div id="drag-container">
        <content></content>
      </div>
    </div>

  </template>
  <script type="application/dart" src="draggable_list_item.dart"></script>
</polymer-element>

你就像

一样使用它
<core-list-dart height="100" data="{{data}}">
  <template>
    <draggable-list-item>
      <test-row data="{{self}}"></test-row>
    </draggable-list-item>
  </template>
</core-list-dart>

test-row看起来像

<polymer-element name="test-row"  unresolved>
  <template>
    <h1>hello I'm a row {{data}}</h1>
  </template>
</polymer-element>

因此测试行(<test-row data="{{self}}"></test-row>)最终会成为

中的内容
<div id="row-container">
  <div id="drag-container">
    <content></content>
  </div>
</div>

正如我之前提到的,ContentElement以神秘的方式表现。为了使其正确呈现,我做了以下

final dragContainer = $['drag-container'];

final ContentElement content = dragContainer.querySelector('content');
print(content.getDistributedNodes());
final dragDiv = new Element.tag('div');
final clonedNodes = content.getDistributedNodes().map((n) =>
    n.clone(true));
clonedNodes.forEach((n) {
  dragDiv.append(n);
});

dragDiv.style.width = '${rect.width}px';
dragDiv.style.height = '${rect.height}px';
dragDiv.style.border = "solid blue 1px";

avatar.append(dragDiv);
dragContainer.style.display = 'none';

我必须获取并克隆内容的分布式节点。这种方法很好,除了我怀疑这也是为什么我在拖拽时丢失部分行的原因。

通常行呈现为

hello I'm a row data item null with value 2

data item null with value 2部分来自I&#39; m使用的数据类的toString。

拖动该部分消失,显示的全部是

hello I'm a row

该部分消失的某个地方,我不确定如何解决它

可悲的是,这只适用于dartium。在Chrome中,当你拖动头像似乎只是保持左上角而且永远不会移动。我怀疑这可能只是dart中core_drag_drop中的一个重要部分。