如何使用 firebase 列表/FirebaseListObservable 在 Angular2 中实现拖放

How to implement drag and drop in Angular2 with a firebase list / FirebaseListObservable

我正在尝试使用 angular2、firebase 和 dragula 实现拖放到列表中。如果已经构建了更好的模块,我就不会使用 dragula,但它看起来很简单。到目前为止,我收到错误是因为 dragula 试图将列表重新排序,就好像它是一个普通数组一样。

<ul class="list-group" [dragula]="statusList" [dragulaModel]='statusService.$statuses'>
<li *ngFor="let status of statusService.$statuses | async" class="list-group-item">
    
    <span class="handle">
        <img src="../../images/handle.png" />
    </span> 
   
    <span class="swatch" [style.backgroundColor]="status.color"></span>
    
    <span class="title">
        <inline-editor type="text" [(ngModel)]="status.title" (keyup.enter)="updateStatus(status, status.title)" (onSave)="updateStatus(status, status.title)" name="title" ngDefaultControl></inline-editor>
    </span>

    <a (click)="statusService.removeStatus(status)" class="remove-status">
        <i class="fa fa-times"></i>
    </a>
                      
</li>
</ul>

我已经使用 firebase 和 angular 使用优先级 属性 实现了拖放。但是,我在 Angular 2 中没有看到明确的方法。

Observables 非常适合创建拖放事件。

基本上,这可以归结为:

  1. 您必须获得对将被拖动的元素的引用
  2. 您必须创建 3 个不同的 Observable:

    let down = Observable.fromEvent(draggedElement, 'mousedown');
    let move = Observable.fromEvent(document, 'mousemove');
    let up = Observable.fromEvent(document, 'mouseup');
    
  3. 您组合 Observables,以便当 draggedElement 上的新 mousedown 发出时,您获取所有 mousemove 事件,直到 mouseup解雇了。

    let dragAndDrop = down.flatMap(() => move.takeUntil(up));
    
  4. 您订阅了 dragAndDrop Observable 瞧瞧

    dragAndDrop.subscribe(position => console.log(position));
    

下面是实施细节:

  1. 我使用 Alexander 的建议订阅了 firebase 列表并创建了一个本地数组:

this.statusService.$statuses.subscribe((statuses: [IStatus]) => {
  this.statuses = []; //reset local array used with dragula for drag and drop
  for (let status of statuses) {
    this.statuses.push(status);
  }
})

  1. 我使用 dragula 的 drop 事件循环遍历并更新数组中每个项目的优先级:

dragulaService.drop.subscribe(() => {
  this.statuses.forEach((status, index) => {
    this.statusService.$statuses.update(status.$key, {
      priority: index
    });
  })
});

  1. 我在查询中按优先级排序:

this.$statuses = this.af.database.list(`/statuses/${session.$key}`, {
  query: {
    orderByChild: 'priority'
  }
});

最后我只使用本地数组作为 dragula 模型和 *ngFor:

<ul class="list-group" [dragula]="statusList" [dragulaModel]='statuses'>

  <li *ngFor="let status of statuses" class="list-group-item">
    
  etc...