如何限制拖放容器仅接受Angular Material拖放特征中的一项

时间:2019-11-26 23:50:34

标签: angular angular-material angular-dragdrop

在使用@ angular / cdk / drag-drop模块(Angular材质拖放)时...是否有任何方法来限制放置容器,以便仅接受一个值而不是多个值?我正在尝试创建一个表单,用户可以在其中拖动图像并将其拖放到应该只有一个项目的字段中。我正在使用标准示例代码从Drag and Drop | Angular Material中实施,但是找不到可以限制放置项目数量的解决方案,第二个找不到用于保持拖动列表相同的解决方案(被拖动的项目将保留在拖动容器中),因此您进行了复制而不是将项目移动到放置容器。有什么解决方案或可以帮助您处理示例代码的人吗?

HTML:

CREATE TEMPORARY TABLE user_data AS
  SELECT
  u.user_id,
  (SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'first_name' LIMIT 1) AS first_name,
  (SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'last_name' LIMIT 1) AS last_name,
  (SELECT `value` FROM wp_bp_xprofile_data WHERE user_id = u.user_id AND field_id = '1' LIMIT 1) AS bp_name,
  (SELECT CONCAT(first_name, ' ', last_name)) AS full_name
FROM
  wp_bp_xprofile_data u
 ;

UPDATE wp_bp_xprofile_data u
  JOIN user_data b
    ON u.user_id=b.user_id 
  SET u.value=b.full_name;

TS:

    <div class="example-container">
  <h2>To do</h2>

  <div
    cdkDropList
    #todoList="cdkDropList"
    [cdkDropListData]="todo"
    [cdkDropListConnectedTo]="[doneList]"
    class="example-list"
    (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let item of todo" cdkDrag>{{item}}</div>
  </div>
</div>

<div class="example-container">
  <h2>Done</h2>

  <div
    cdkDropList
    #doneList="cdkDropList"
    [cdkDropListData]="done"
    [cdkDropListConnectedTo]="[todoList]"
    class="example-list"
    (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let item of done" cdkDrag>{{item}}</div>
  </div>
</div>

4 个答案:

答案 0 :(得分:1)

好的,这应该可以工作:

movementCount: number = 0;

drop(event: CdkDragDrop<string[]>) {
   if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else if(this.movementCount === 0){
       this.movementCount++;  // block next object from being moved
       // copy obj being moved
       var movingObj = event.previousContainer.data[event.previousIndex];

       transferArrayItem(event.previousContainer.data,
                    event.container.data,
                    event.previousIndex,
                    event.currentIndex);

       // transfer complete so copy object back
       event.previousContainer.data.push(movingObj);    
  }
}

我使用计数器来确定是否允许移动,但布尔值也可以(更好)工作。 您只需要添加一些额外的代码,以便在将图像从div中删除/删除时,计数器将返回零/ false,因此可以根据需要拖动其他图像。

希望有帮助。

答案 1 :(得分:1)

这是我允许覆盖的 working demo 版本。

确保您的屏幕足够宽,您可以看到两列。


你应该使用 cdkDropListEnterPredicate

如果您的目的地“空位”已经填满,只需从这里返回 false。

请注意,您的处理程序是从 this 不是您的组件的上下文中调用的。所以你需要在你的组件中使用这样的 lambda 函数。

destinationNotEmptyPredicate = () => 
{
   return this.destinationArray.length == 0;
};

确保目的地列表的高度可以让您真正将东西放入其中。

但是,如果您需要允许覆盖“假列表”中现有的单个项目(您可能会这样做),那么这就有点棘手了。您不会想要使用此谓词(因为它会阻止您删除任何内容,除非您先删除现有项目)。

因此,在这种情况下,您需要进行 css 调整以隐藏已经存在的项目(当您将鼠标悬停在它上面时)。

#even 是目的地列表。

#even.cdk-drop-list-dragging .cdk-drag:not(.cdk-drag-placeholder) {
   display: none;
}

同时设置 [cdkDropListSortingDisabled]="false" 以避免出现奇怪的动画故障。

当您“删除”项目时,您的目的地列表应该只包含一个项目:

drop(event: CdkDragDrop<number[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    } else {
      this.even = [event.item.data];
    }
  }

请注意我在这里仍然使用 cdkDropListEnterPredicate 来只允许删除偶数。

答案 2 :(得分:0)

另一种解决方案是将 import Results from "./Results"; const CompanyInfoList = ({ filtered }) => { const fltr = filtered.map((result) => ( <Results key={result.id} name={result.name} employee={result.employee} date={result.date} amount={result.amount} /> )); return <div>{fltr}</div>; }; export default CompanyInfoList; 设置为硬编码的空列表。所以这是从 cdk 的角度来看的一个列表,但并不是真正适合您的应用。

然后您只需在该位置显示您想要的任何内容(如果该项目已设置),并处理 [cdkDropListData]="[]" 事件以更新它。

cdkDragDrop

答案 3 :(得分:0)

不确定它是否仍然有用,但我已经使用了 2 方法将放置的项目限制为仅 1,并在放置另一个项目时取消前一个放置的项目:

  1. 禁用 HTML 中的排序

    cdkDropListSortingDisabled

  2. .ts 中将项目总数限制为 1,并删除索引 1 处的项目(已在其中的项目),因为排序禁用将添加下一个位于索引 0

在您的 onDrop 方法中添加以下函数:

for (let  i=0 ; i<2 ; i++){
   this.items.splice( 1 ,1)
}