4

我想使用 Observable 作为材质拖放的数据源,但我现在正在苦苦挣扎。基本上,我在看板中有一个泳道列表,每个泳道都有一堆我想移动的项目。当我移动一个项目时,我也想更新后端。多人也将更新同一个看板,所以我也想使用 socket.io 来自动移动项目(出于同样的原因,我也在为此苦苦挣扎)

这是模板:

<button mat-raised-button color="primary" (click)="addItem()">Add Item</button>

<button mat-raised-button color="primary" (click)="moveItem()" style="margin-left:10px">Move Item</button>

<div cdkDropListGroup>
<div class="example-container" *ngFor="let lane of swimlanes">
  <h2>{{lane.name}}</h2>

  <div
    cdkDropList
    #doneList="cdkDropList"
    [cdkDropListData]="lane.array | async"
    class="example-list"
    (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let item of lane.array | async" cdkDrag>{{item.name}}</div>
  </div>
</div>

</div>

这是组件代码:

import {Component, OnInit} from '@angular/core';
import {CdkDragDrop, moveItemInArray, transferArrayItem} from '@angular/cdk/drag-drop';
import { Subscription, of, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Swimlane{
  name: string;
  array: Observable<Task[]>;
}

export interface Task{
  name: string;
  list: string;
}

/**
 * @title Drag&Drop connected sorting
 */
@Component({
  selector: 'cdk-drag-drop-connected-sorting-example',
  templateUrl: 'cdk-drag-drop-connected-sorting-example.html',
  styleUrls: ['cdk-drag-drop-connected-sorting-example.css'],
})
export class CdkDragDropConnectedSortingExample implements OnInit {

//These will eventually come from an API.
  items:Task[] = [
    {name: "Get to work", list: "To Do"},
    {name: "Pick up groceries", list: "To Do"},
    {name: "Go home", list: "To Do"},
    {name: "Fall asleep", list: "To Do"},
    {name: "Get up", list: "Done"},
    {name: "Brush teeth", list: "Done"},
    {name: "Take a shower", list: "Done"},
    {name: "Check e-mail", list: "Done"},
    {name: "Walk dog", list: "Done"}
  ];


  swimlanes:Swimlane[] = [];

//Create Observables as the data sources
  itemsObservable:Observable<Task[]>;

  todo:Observable<Task[]>;
  done:Observable<Task[]>;

  ngOnInit(): void {

    this.itemsObservable = of(this.items);

    this.todo = this.itemsObservable.pipe(
       map((item:Task[]) => item.filter((item:Task) => item.list === "Done")
     ));

    this.done = this.itemsObservable.pipe(
       map((item:Task[]) => item.filter((item:Task) => item.list === "To Do")
     ));    

    this.swimlanes.push({name:"To Do", array: this.todo});
    this.swimlanes.push({name:"Done", array: this.done});
  }

addItem(){
  this.items.push({name: "New Item", list: "To Do"});
  console.log(this.items.length);
}

moveItem(){

}

  drop(event: CdkDragDrop<string[]>) {

    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      transferArrayItem(event.previousContainer.data,
                        event.container.data,
                        event.previousIndex,
                        event.currentIndex);
    }
  }
}

这是我尝试使用可观察对象作为数据源的堆栈闪电战。您可以看到它正确加载了通道,但是当您尝试移动其中一个项目时,它会消失。有任何想法吗?

在我的实际应用程序中,我从 API 请求中接收值。所以它会自动作为一个 Observable 进来。然后我闯入一个本地基本数组并取消订阅 Observable。然后我从本地基础数组创建一个新的 Observable 并对本地基础数组进行更改,希望这些更改会反映在拖放中。但这目前不起作用。

很高兴编写我自己的移动功能,但没有反映可观察数据源更改的车道,我无法让它工作。

4

1 回答 1

4

我遇到了同样的问题。显然 Angular DnD 不喜欢 cdkDropListData 中的 observables。不过有一个解决办法。

总体思路是不使用 observables 作为 droplist 的数据源,而是使用 observables.subscribe 填充 droplist 的数据源。

所以代替这个:

this.swimlanes.push({name: "To Do", array: this.todo})

我这样做了:

this.todo.subscribe(data => {
  console.log(data)
  this.swimlanes.push({name: "To Do", array: data})
})

您必须从 subscribe 方法将数据填充到泳道。

我分叉了你的 stackblitz 并让它工作。

stackblitz前叉

我希望这有帮助。

将新项目添加到待办事项列表:

addItem(){
  this.baseTaskList.subscribe(items => {
    this.swimlanes[0]["array"]
      .push({"task": "New Task", "list":"To Do"})
      })
  }

您将在 http 帖子的订阅中将新项目添加到下拉列表容器中,假设您还将通过某些 API 将新项目发布到某种数据库中。post的响应将是您需要添加到本地容器中的项目的新插入项目的ID,以便将来需要知道行ID(删除,更新)的数据操作

于 2020-07-06T22:27:19.537 回答